Now we start with the first Django application for our project “cookbook”.
This is how the data model looks like:
Because the application will manage recipes we will call it recipes:
$ cd cookbook
$ python manage.py startapp recipes
This command will create a directory recipes containing these four files:
recipes
|-- __init__.py
|-- models.py
|-- tests.py
`-- views.py
Now open the file models.py in a text editor. It contains only a single import:
from django.db import models
To prevent problems with the encoding add the following line before the import:
# encoding: utf-8
Now start with the model for the categories:
# encoding: utf-8
from django.db import models
class Category(models.Model):
"""Category model."""
name = models.CharField('Name', max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField('Description', blank=True)
The next step is to extend the class Category:
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __unicode__(self):
return self.name
Let’s start with the second model for the recipes:
class Recipe(models.Model):
"""Recipe model."""
title = models.CharField('Title', max_length=255)
slug = models.SlugField(unique=True)
ingredients = models.TextField('Ingredients',
help_text='One ingredient per line')
preparation = models.TextField('Preparation')
time_for_preparation = models.IntegerField('Time for preparation',
help_text='Time in minutes', blank=True, null=True)
number_of_portions = models.PositiveIntegerField('Number of portions')
difficulty = models.SmallIntegerField('Difficulty',
choices=DIFFICULTIES, default=DIFFICULTY_MEDIUM)
category = models.ManyToManyField(Category, verbose_name='Categories')
author = models.ForeignKey(User, verbose_name='Author')
photo = models.ImageField(upload_to='recipes', verbose_name='Photo')
date_created = models.DateTimeField(editable=False)
date_updated = models.DateTimeField(editable=False)
We habe to add another import for the User class:
from django.contrib.auth.models import User
Add some constants for the difficulty field at the top of the class:
DIFFICULTY_EASY = 1
DIFFICULTY_MEDIUM = 2
DIFFICULTY_HARD = 3
DIFFICULTIES = (
(DIFFICULTY_EASY, 'simple'),
(DIFFICULTY_MEDIUM, 'normal'),
(DIFFICULTY_HARD, 'hard'),
)
Again we have to add a Meta class and a __unicode__ method for the Recipe class:
class Meta:
verbose_name = 'Recipe'
verbose_name_plural = 'Recipes'
ordering = ['-date_created']
def __unicode__(self):
return self.title
Because we want to populate the date fields automatically we have to overload the save method:
def save(self, *args, **kwargs):
if not self.id:
self.date_created = now()
self.date_updated = now()
super(Recipe, self).save(*args, **kwargs)
At the end of the save method we call the super function to call the parent method.
Finally we have to add the now function at the top of the file:
from django.utils.timezone import now
Note
PEP 8, the Python documentation and this short article provide more information about the import statement.
When everything is complete, the file models.py should look as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | # encoding: utf-8
from django.contrib.auth.models import User
from django.db import models
from django.utils.timezone import now
class Category(models.Model):
"""Category model."""
name = models.CharField('Name', max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField('Description', blank=True)
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __unicode__(self):
return self.name
class Recipe(models.Model):
"""Recipe model."""
DIFFICULTY_EASY = 1
DIFFICULTY_MEDIUM = 2
DIFFICULTY_HARD = 3
DIFFICULTIES = (
(DIFFICULTY_EASY, 'simple'),
(DIFFICULTY_MEDIUM, 'normal'),
(DIFFICULTY_HARD, 'hard'),
)
title = models.CharField('Title', max_length=255)
slug = models.SlugField(unique=True)
ingredients = models.TextField('Ingredients',
help_text='One ingredient per line')
preparation = models.TextField('Preparation')
time_for_preparation = models.IntegerField('Time for preparation',
help_text='Time in minutes', blank=True, null=True)
number_of_portions = models.PositiveIntegerField('Number of portions')
difficulty = models.SmallIntegerField('Difficulty',
choices=DIFFICULTIES, default=DIFFICULTY_MEDIUM)
category = models.ManyToManyField(Category, verbose_name='Categories')
author = models.ForeignKey(User, verbose_name='Author')
photo = models.ImageField(upload_to='recipes', verbose_name='Photo')
date_created = models.DateTimeField(editable=False)
date_updated = models.DateTimeField(editable=False)
class Meta:
verbose_name = 'Recipe'
verbose_name_plural = 'Recipes'
ordering = ['-date_created']
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id:
self.date_created = now()
self.date_updated = now()
super(Recipe, self).save(*args, **kwargs)
|
Open the file settings.py and add the name of our new application at the end of the INSTALLED_APPS setting.
Now INSTALLED_APPS looks like this:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'recipes',
)