The most important part of a model-and the only required part of a model-is the list of database fields it defines.
Django places only two restrictions on model field names:
- A field name cannot be a Python reserved word, because that would result in a Python syntax error. For example:
class Example(models.Model): pass = models.IntegerField() # 'pass' is a reserved word!
- A field name cannot contain more than one underscore in a row, due to the way Django's query lookup syntax works. For example:
class Example(models.Model): # 'foo__bar' has two underscores! foo__bar = models.IntegerField()
Each field in your model should be an instance of the appropriate Field
class. Django uses the field class types to determine a few things:
- The database column type (for example,
INTEGER
,VARCHAR
) - The widget to use in Django's forms and admin site, if you care to use it (for example,
<input type="text">
,<select>
) - The minimal validation requirements, which are used in Django's admin interface and by forms
Each field class can be passed a list of option arguments, for example when we were building the book model in Chapter 4, Models, our num_pages
field looked like this:
num_pages = models.IntegerField(blank=True, null=True)
In this case, we are setting the blank
and null
options for the field class. Table A.2 lists all the field options in Django.
A number of fields also define additional options specific to that class, for example the CharField
class has a required option max_length
which defaults to None
. For example:
title = models.CharField(max_length=100)
In this case we are setting the max_length
field option to 100 to limit our book titles to 100 characters.
A complete list of field classes is in Table A.1, sorted alphabetically.
Field |
Default Widget |
Description |
---|---|---|
|
N/A |
An |
|
|
A 64-bit integer, much like an |
|
N/A |
A field to store raw binary data. It only supports |
|
|
A true/false field. If you need to accept |
|
|
A string field, for small- to large-sized strings. For large amounts of text, use |
|
|
A date, represented in Python by a |
|
|
A date and time, represented in Python by a |
|
|
A fixed-precision decimal number, represented in Python by a |
|
|
A field for storing periods of time-modeled in Python by |
|
|
A |
|
|
A file upload field. For more information on |
|
|
A |
|
|
A floating-point number represented in Python by a |
|
|
Inherits all attributes and methods from |
|
|
An integer. Values from |
|
|
An IPv4 or IPv6 address, in string format (for example, |
|
|
Like a |
|
|
An integer . Values from |
|
|
Slug is a newspaper term. A slug is a short label for something, containing only letters, numbers, underscores or hyphens. |
|
|
Like an |
|
|
A large text field. If you specify a |
|
|
A time, represented in Python by a |
|
|
A |
|
|
A field for storing universally unique identifiers. Uses Python's |
Table A.1: Django model field reference
The primary_key
and unique
arguments are not supported, and will raise a TypeError
if used.
- Has two optional arguments: FileField.upload_to
FileField.storage
A local filesystem path that will be appended to your MEDIA_ROOT
setting to determine the value of the url
attribute. This path may contain strftime()
formatting, which will be replaced by the date/time of the file upload (so that uploaded files don't fill up the given directory). This may also be a callable, such as a function, which will be called to obtain the upload path, including the filename. This callable must be able to accept two arguments, and return a Unix-style path (with forward slashes) to be passed along to the storage system.
The two arguments that will be passed are:
- Instance: An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached. In most cases, this object will not have been saved to the database yet, so if it uses the default
AutoField
, it might not yet have a value for its primary key field. - Filename: The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path.
A storage object, which handles the storage and retrieval of your files. The default form widget for this field is a ClearableFileInput
. Using a FileField
or an ImageField
(see below) in a model takes a few steps:
- In your settings file, you'll need to define
MEDIA_ROOT
as the full path to a directory where you'd like Django to store uploaded files. (For performance, these files are not stored in the database.) DefineMEDIA_URL
as the base public URL of that directory. Make sure that this directory is writable by the web server's user account. - Add the
FileField
orImageField
to your model, defining theupload_to
option to specify a subdirectory ofMEDIA_ROOT
to use for uploaded files. - All that will be stored in your database is a path to the file (relative to
MEDIA_ROOT
). You'll most likely want to use the convenienturl
attribute provided by Django. For example, if yourImageField
is calledmug_shot
, you can get the absolute path to your image in a template with{{ object.mug_shot.url }}
.
Note that whenever you deal with uploaded files, you should pay close attention to where you're uploading them and what type of files they are, to avoid security holes. Validate all uploaded files so that you're sure the files are what you think they are. For example, if you blindly let somebody upload files, without validation, to a directory that's within your web server's document root, then somebody could upload a CGI or PHP script and execute that script by visiting its URL on your site. Don't allow that.
Also note that even an uploaded HTML file, since it can be executed by the browser (though not by the server), can pose security threats that are equivalent to XSS or CSRF attacks. FileField
instances are created in your database as varchar
columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length
argument.
When you access a FileField
on a model, you are given an instance of FieldFile
as a proxy for accessing the underlying file. In addition to the functionality inherited from django.core.files.File
, this class has several attributes and methods that can be used to interact with file data:
A read-only property to access the file's relative URL by calling the url()
method of the underlying Storage
class.
Behaves like the standard Python open()
method and opens the file associated with this instance in the mode specified by mode
.
Behaves like the standard Python file.close()
method and closes the file associated with this instance.
This method takes a filename and file contents and passes them to the storage class for the field, then associates the stored file with the model field. If you want to manually associate file data with FileField
instances on your model, the save()
method is used to persist that file data.
Takes two required arguments: name
which is the name of the file, and content
which is an object containing the file's contents. The optional save
argument controls whether or not the model instance is saved after the file associated with this field has been altered. Defaults to True
.
Note that the content
argument should be an instance of django.core.files.File
, not Python's built-in file object. You can construct a File
from an existing Python file object like this:
from django.core.files import File # Open an existing file using Python's built-in open() f = open('/tmp/hello.world') myfile = File(f)
Or you can construct one from a Python string like this:
from django.core.files.base import ContentFile myfile = ContentFile("hello world")
Deletes the file associated with this instance and clears all attributes on the field. This method will close the file if it happens to be open when delete()
is called.
The optional save
argument controls whether or not the model instance is saved after the file associated with this field has been deleted. Defaults to True
.
Note that when a model is deleted, related files are not deleted. If you need to clean up orphaned files, you'll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via for example, cron
).