Hour 2 mentioned that Django uses data models to define classes of data objects that belong to a particular application. Each application has its own models.py file that contains the Python code that defines that application's data model.
Django has an extensive package, models.django.db, that contains several predefined class field types that help you define data objects as well as a set of options to manage the behavior of those fields.
Did you Know?
Django has a backend engine that runs SQL commands to create tables for each object and relationship.
You can add several different types of fields to your data model. The benefit of having different types of fields is that the Django engine can understand what type of data should be in the field. Django has built-in validation that simplifies the process of verifying that the right type of data is being added to an object in the model. Django also can use the field type to display the field properly in predefined and admin views.
The following sections describe some of the field types that you will use the most.
You will use two main field types for simple text fields.
The CharField type is designed for smaller strings with specific length limitations, such as names or titles. CharField tells Django that the field is expecting text data. It requires that a maximum length be specified using the max_length argument:
name = models.CharField('Name', max_length=100)
The TextField type is designed for larger strings of text, such as a description. TextField tells Django that the field is expecting a variable amount of text. You can specify a maximum size for TextField using the max_length argument, as shown here, but this is not required:
desc = models.TextField('Desc', max_length=1000)
You can use three different types of fields when adding date and time fields to your models. DateField, TimeField, and DateTimeField are designed to accept a date, time, and date with time of day value, respectively:
bday = models.DateField('Birthday') alarm = models.TimeField('Alarm') appnt = models.DateTimeField('Appointment')
All three date and time field types accept the following two optional arguments:
auto_now tells Django to automatically set the value of this field to the current time each time the object is saved. This is useful for last-saved time stamps.
auto_now_add tells Django to automatically set the value of this field to the current time when it is initially created. This is useful for creation time stamps.
EmailField is similar to CharField, with two notable differences. Django verifies that the value entered into this field is a valid email address. Also, this field does not accept the max_length argument. The maximum length is automatically set to 75 characters.
You will use two types of file fields. The first is the standard FileField, which is used to upload files to the website. FileField requires an upload_to argument that specifies a path, relative to MEDIA_ROOT, on the local file system of the web server to store the file, as shown here:
doc = models.FileField('File', upload_to='documents')
By the Way
The MEDIA_ROOT path is specified in the settings.py file. No path is defined by default, so you must define one.
Did you Know?
The path you specify in upload_to can contain Python's strftime formatting, which is replaced by the data and time of the file upload. This can be useful if you want to control file uploads.
The second type of field is the ImageField. The ImageField is very similar to the FileField except that in validation, the ImageField will validate the file as a valid image file. The ImageField also includes two extra optional arguments, height_field and width_field that contain height and width of the image. These fields are autopopulated when the object is saved.
URLField is similar to TextField. It also accepts the max_length argument. URLField also accepts the verify_exists argument. If this argument is set to True (the default), Django checks the URL to verify that it exists before accepting it:
location = models.URLField('WebPage', verify_exists=True, max_length=100)
Try It Yourself: Add Fields to a ModelThe previous sections have discussed several different types of fields that can be applied to a model for specific purposes. In this section, you apply that knowledge to extend the Person class by adding fields to it. Follow these steps to add a DateField, EmailField, and URLField to the Person class in the iFriends database:
|
Django provides several options that can be applied to fields to control their behavior in the SQL database as well as Django's admin interface. The following sections discuss some of the most common options that can be passed as arguments to field definitions. These arguments are all optional and are available to all Django field types.
Django provides two different options that allow you to leave fields blank when adding new objects. The null option tells Django to store any fields left blank as the NULL in the database:
count = models.Integer('count', null=True)
The blank option tells Django's validation engine to allow the field to be left blank:
count = models.Integer('count', blank=True)
There is a big difference between the null and blank options. The null option is strictly at the database level. The blank option is used by the validation engine on the Django admin site. This means that if you want to allow null values to be stored in the database and accessed in your code, you will need to set both the null and blank options to True.
Watch Out!
Use the null=True argument on only nonstring-type fields such as dates, files, and integers. When you use the blank=True option, Django stores the empty string as the value of the field.
Did you Know?
Both the blank and null options are set to False by default. If you want to allow fields to be left blank in web forms and in the database, you must set these options to True.
The default option allows you to specify a value that will be applied to the field by default:
title = models.Integer('Title', default='<no title>')
The choices field option allows you to specify a list of two tuples to use as viable values in the field. Django's model validation accepts only values specified in the choices field option when validating form entry. When this option is used, the Django admin interface provides a selection box for you to make your choice.
By the Way
The value of choices doesn't necessarily need to be a list or tuple. It can be any Python iterable object.
This code snippet shows how to add a list of choices to a field definition:
gender_list = (('M', 'Male'), ('F', 'Female' )) . . . gender = models.CharField(max_length=1, choices=gender_list)
The core field option is used when you relate objects to another object in the model. The Django admin interface lets you specify that multiple objects that are related to each other can be edited inline together.
Fields that have core=True set are treated as required fields in the object. When all the fields that have core=True set are cleared in the admin interface, the object is deleted.
The editable field can be useful if you have a field, such as the modified time stamp shown here, that you do not want to be edited by the admin interface or Django's default forms. Fields are editable by default. However, if you specify editable=False, they cannot be changed in Django's admin interface:
last_modified = models.DateTimeField('Last Modified', auto_now_add=True, editable=False)
The primary_key field option allows you to specify which field will be used for the primary key in the database. If you set primary_key=True for a field, blank=False, null=False, and unique=True are implied for the field. Only one primary key is allowed per object.
If you don't specify a primary key for an object, Django adds the following field behind the scenes:
id=models.AutoField('ID', primary_key=True)
The unique field option allows you to specify if you want the field's value to be unique throughout the table in the database. When unique=True is set, values are not allowed if they already exist for that field in another object in the database. The unique option is enforced at both the Django admin validation level and the database level.
Django also provides the following field options that allow you to specify uniqueness of objects based on date:
unique_for_date: When this option is set to True for a DateField or DateTimeField, Django enforces uniqueness in the date of that field.
unique_for_month: When this option is set to True for a DateField or DateTimeField, Django enforces uniqueness in the month of that field.
unique_for_year: When this option is set to True for a DateField or DateTimeField, Django enforces uniqueness in the year of that field.
By the Way
The unique_for_date, unique_for_month, and unique_for_year options are enforced only at the Django admin validation level.
Try It Yourself: Add Options to Fields in a ModelThe previous sections have discussed several different options that can be applied to fields that control the behavior of the fields in the admin interface and also in the database. In this section, you apply that knowledge to modify the Person class by adding options to fields. Follow these steps to force the email field to be unique, to allow the birthday and desc fields to be blank in the admin interface and the database, and to add a gender choice field to the class:
You should see the Gender field now available in the admin interface. Also, the Birthday field label is no longer bold, which means that this field may be left blank. The Desc field is bold because the blank option was not set to True. Remember that you don't need to set the blank option for CharField, because Django allows a zero-length string. |
As you begin to develop more complex websites using Django, you will find it necessary to link classes within models and also link classes in other models. Django provides a simple but effective means of accomplishing class relationships. The following sections discuss how to define class relationships within models.
Arguably the most common type of relationship you will deal with is the many-to-one relationship, in which one object can be related to several others.
Many-to-one relationships are defined by adding a ForeignKey field to a class and specifying a second class as the key. For example, our sample website currently has a Person class defined. If we were to add a Hometown class, several people might come from the same hometown. The code used to define the many-to-one relationship would be similar to the following:
class Hometown(models.model): . . . class Person(models.Model): hometown = models.ForeignKey(Hometown)
If a module has not yet been defined, you can also specify the name of the object instead of the object itself as the argument to ForeignKey. For example:
class Person(models.Model): hometown = models.ForeignKey('Hometown') . . . class Hometown(models.model):
Did you Know?
You can create a recursive relationship within an object by specifying self as the argument to ForeignKey:
. . . models.ForeignKey('self')
The following are some of the more common optional arguments that you will use with ForeignKey:
edit_inline defines how the object will be edited in the admin interface. If it is set to False, the object is edited inline on the related object's page. If it is set to models.TABULAR, the object is edited as a table. If it is set to models.STACKED, the fields for each object are displayed as stacked on top of each other.
related_name can be set to the name to be used from the related object back to this one.
to_field specifies the field in the related object this field relates to. This defaults to the primary key of the related object.
Many-to-many relationships are defined by adding a ManyToMany field to a class and specifying a second class as the key. For example, our sample website currently has a Person class defined. If we were to add a Blog class, we might have several persons who belong to several blogs and several blogs that have several people using them. The code used to define the many-to-many relationship would be similar to the following:
class Blog(models.model): . . . class Person(models.Model): blogs = models.ManyToManyField(Blog)
Did you Know?
You can create a recursive relationship within an object by specifying self as the argument to ManyToMany:
friends = models.ManyToManyField('self')
The following are some of the more common optional arguments you will use with ManyToManyField:
filter_interface can be set to models.VERTICAL or models.HORIZONTAL to tell Django to use a built-in JavaScript interface to display the field in the admin form.
related_name can be set to the name to be used from the related object back to this one.
symmetrical is used when you use self as the object for the relationship. Setting symmetrical=True tells Django that the relationship between the two objects is reciprocal. In other words, if it exists in one, it also exists in the other.
Quoted from djangoproject.com: "The semantics of one-to-one relationships will be changing soon, so we don't recommend that you use them."
One-to-one relationships are defined by adding a OneToOne field to a class and specifying a second class as the key. For example, our sample website currently has a Person class defined. If we were to add an Alias class that limits each person to have only one Alias, the code used to define the one-to-one relationship would be similar to the following:
class Alias(models.model): . . . class Person(models.Model):
Try It Yourself: Add Many-to-One and Many-to-Many Relationships to a ModelThe preceding section discussed the different types of relationships that you can add between objects. This section takes you through the steps of adding some relationships to the People model in your iFriends application. In this section, you will add a many-to-one relationship between the Person class and the User class in Django's authentication system. You also will create a recursive relationship between the Person class and itself, as well as a many-to-many relationship between the Person class and a new Blog class.
In this example, you imported the User class from django.contrib.auth.models so that you can use it as the ForeignKey field. Using the ForeignKey field in this way allows you to access the Django User object from a Person object. You will see this in action later in the book. |