Making fields optional

After you play around with the admin site for a while, you'll probably notice a limitation-the edit forms require every field to be filled out, whereas in many cases you'd want certain fields to be optional. Let's say, for example, that we want our Author model's email field to be optional-that is, a blank string should be allowed. In the real world, you might not have an e-mail address on file for every author.

To specify that the email field is optional, edit the Author model (which, as you'll recall from Chapter 4, Models, lives in mysite/books/models.py). Simply add blank=True to the email field, like so:

class Author(models.Model): 
    first_name = models.CharField(max_length=30) 
    last_name = models.CharField(max_length=40) 
    email = models.EmailField(blank=True)

This tells Django that a blank value is indeed allowed for author's e-mail addresses. By default, all fields have blank=False, which means blank values are not allowed.

There's something interesting happening here. Until now, with the exception of the __str__() method, our models have served as definitions of our database tables-Pythonic expressions of SQL CREATE TABLE statements, essentially. In adding blank=True, we have begun expanding our model beyond a simple definition of what the database table looks like.

Now, our model class is starting to become a richer collection of knowledge about what Author objects are and what they can do. Not only is the email field represented by a VARCHAR column in the database; it's also an optional field in contexts such as the Django admin site.

Once you've added that blank=True, reload the Add author edit form (http://127.0.0.1:8000/admin/books/author/add/), and you'll notice the field's label-Email-is no longer bolded. This signifies it's not a required field. You can now add authors without needing to provide e-mail addresses; you won't get the loud red This field is required message anymore, if the field is submitted empty.

Making date and numeric fields optional

A common gotcha related to blank=True has to do with date and numeric fields, but it requires a fair amount of background explanation. SQL has its own way of specifying blank values-a special value called NULL. NULL could mean "unknown", or "invalid", or some other application-specific meaning. In SQL, a value of NULL is different than an empty string, just as the special Python object None is different than an empty Python string ("").

This means it's possible for a particular character field (for example a VARCHAR column) to contain both NULL values and empty string values. This can cause unwanted ambiguity and confusion: Why does this record have a NULL but this other one has an empty string? Is there a difference, or was the data just entered inconsistently? and: How do I get all the records that have a blank value-should I look for both NULL records and empty strings, or do I only select the ones with empty strings?

To help avoid such ambiguity, Django's automatically generated CREATE TABLE statements (which were covered in Chapter 4, Models) add an explicit NOT NULL to each column definition. For example, here's the generated statement for our Author model, from Chapter 4, Models:

CREATE TABLE "books_author" ( 
    "id" serial NOT NULL PRIMARY KEY, 
    "first_name" varchar(30) NOT NULL, 
    "last_name" varchar(40) NOT NULL, 
    "email" varchar(75) NOT NULL 
); 

In most cases, this default behavior is optimal for your application and will save you from data-inconsistency headaches. And it works nicely with the rest of Django, such as the Django admin site, which inserts an empty string (not a NULL value) when you leave a character field blank.

But there's an exception with database column types that do not accept empty strings as valid values-such as dates, times, and numbers. If you try to insert an empty string into a date or integer column, you'll likely get a database error, depending on which database you're using. (PostgreSQL, which is strict, will raise an exception here; MySQL might accept it or might not, depending on the version you're using, the time of day and the phase of the moon.)

In this case, NULL is the only way to specify an empty value. In Django models, you can specify that NULL is allowed by adding null=True to a field. So that's a long way of saying this: if you want to allow blank values in a date field (for example DateField, TimeField, DateTimeField) or numeric field (for example IntegerField, DecimalField, FloatField), you'll need to use both null=True and blank=True.

For sake of example, let's change our Book model to allow a blank publication_date. Here's the revised code:

class Book(models.Model): 
    title = models.CharField(max_length=100) 
    authors = models.ManyToManyField(Author) 
    publisher = models.ForeignKey(Publisher) 
    publication_date = models.DateField(blank=True, null=True)

Adding null=True is more complicated than adding blank=True, because null=True changes the semantics of the database-that is, it changes the CREATE TABLE statement to remove the NOT NULL from the publication_date field. To complete this change, we'll need to update the database. For a number of reasons, Django does not attempt to automate changes to database schemas, so it's your own responsibility to execute the python manage.py migrate command whenever you make such a change to a model. Bringing this back to the admin site, now the Add book edit form should allow for empty publication date values.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset