Understanding Models

Storing and retrieving information in a database is a common task for web applications. To meet these needs, Django comes with robust database management features. Generally speaking, these features allow you to do two things; 1) design database schemas; i.e., tables, relationships, etc, 2) manage the data in a database; i.e., write, read, update, delete, query, etc.

Here are a few things you should know about Django's database toolset:

  • Django's DB toolset is often referred to as an object-relational mapper (ORM) because it translates the way databases are traditionally managed (e.g. SQL) into something that is more Pythonic
  • Database tables are created via Python classes. That's part of what makes them easy to work with - if you know how to create classes and give them attributes, then you're well on your way to designing tables in Django
  • Since tables are created as classes, it's logical that fields are simply class attributes
  • These classes are created in the models.py file. When you create a Django app there's a models.py created by default

Here is some additional information about models and fields.

Defining Models

In Django, database tables are referred to as models. These models are created in the models.py file, which is located in each Django app directory. A model is just a Python class. To define a model you need to give it a class name, subclass it from Django's included models.Model class, and then define fields. Here's what a simple model design might look like.

from django.db import models

class Bottle(models.Model):

Defining Fields

A model is only valid when it has one or more fields. Fields are created by adding attributes to the model class. Continuing the example from above, here's what adding fields would look like.

from django.db import models

class Bottle(models.Model):
    size = models.IntegerField()
    color = models.CharField(max_length=100)

Let's break down line 4. The field name, size, is something you create. You can choose almost any name as long as it doesn't conflict with any of the models API names. The second part, models.IntegerField(), is creating an instance of a Field class. Django comes with dozens of built in field types. By doing this you are telling the database what kind of data you want to save in that field. This recognizes that a database usually stores a variety of different kinds of data - some data is simple text, which CharField() can be used for. Other data might be an integer, date, email address, all which have their own pre-built field class.

Database Design Tip: It's important to always match up your data type with the right field class.

What about the ID Field?

A typical requirement of database tables is that they have one field that can uniquely identify a row i.e. object. Why is this important? Let's say you want to find a specific object in a table. If the object doesn't have at least one unique field then there's a possibility it will be difficult or impossible to find. The id field is the objects "unique address" in the table.

This field us usually named id, and is a number that gets incremented upon the creation of new objects. Django will automatically create the id field for each model. It is possible to override it, but that is not needed in this project.

Table Relationships

One of the innovations of Relational Databases is the ability to link, or relate, objects in different tables. This is actually a complex topic with large volumes written on the matter. This lesson doesn't have the luxury of doing this topic the justice it deserves, however, a simple explanation will be given because a baseline understanding is useful in order to proceed in this project.

A quick side note. Database design is both art and science. Some developers believe in the hard and fast rules of DB design and will try to stick to them always, while others will be more lax. Here I'll make some authoritative statements, but keep in mind there are exceptions to every rule. As you become more experienced doing this you'll be able to make your own call.

To help work through these concepts let's use an example. Let's say that you want a database to save information about people living in your neighborhood. You want to know who lives in your neighborhood, and what their address is.

If you were in a rush you might create one table named Person. This table might have fields like, first_name, last_name, address, city, and state. There are a couple of problems with doing it this way though:

  • If more than one person lives in the house, you'll have redundant data in the address, city, and state fields for each person living in the house. This might not be a big deal if the neighborhood is small, but if the dataset is large, then all of the sudden you'll be storing a large amount of duplicate data and will need to spend real dollars on storage infrastructure.
  • If a family moves to a house a few doors down, now you have to update the address in multiple locations. That means you have to query the database multiple times to update it. Again, not a big deal on a small neighborhood, but once the dataset grows it could be a problem. It also requires more code on the developer's part.

There's an easier way - table relationships. A different way to create this database would be to have two different tables; one named Person and one named Address. The Person table would have the first_name, last_name, and address_id fields. The address_id field would be a special relational field that the database uses to link the Person object to a Address object. The Address table would now have address, city, and state fields.

This design will help reduce the amount of duplicate data in the database, and will make updating the address objects easier.

Track your progress with a free account