Simple Django Tip #4
Points to remember while designing a model
So far my tips were more about the environment and setting up the stage in the right way.
Let's look at a few key points to remember while defining a model
in models.py.
I plan to write a couple of posts regarding model design, rather than one single long post.
Models in Django
A model
in the Django ORM world is the equivalent of a table in the database. That's the beauty of ORMs. We can define the complete table structure in the application itself, create, modify, query and do every single thing that we do using SQLs but without them.
Let's jump in straight ๐. To not repeat myself I'd urge you to refer to my previous post to perform the usual steps of creating a Django project and other steps.
I'm a big fan of popsicles and soft cones ๐ฆ๐. Just to give the post a bit of flavor, I decided to take an example of defining a few models
for a hypothetical website that sells and delivers ice cream.
A few models for our ice cream website would be:
Customer
Icecream
Order
Now for a few tips to keep in mind while we define a model. We shall apply them in the end to these models to see what it looks like.
Tips to remember while defining a model
Use descriptive field names
This may seem like an age-old tip. But it is forgotten many a time ๐. Do not worry about the name of a field being long as long as it is self-explanatory.
# WRONG
class Customer(models.Model):
fname = models.CharField(...)
lname = models.CharField(...)
# RIGHT
class Customer(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
Use descriptive related names
Tables being related is extremely common in any database. In Django, while we use ForeignKey
as field type, make sure to give an understandable value for related_name
.
If not followed from the beginning, it becomes unnecessarily complicated when the number of models starts to grow. I generally use the approach of noun + verb combination. Feel free to use whatever suits your naming standards but make sure it's descriptive. Let's see an example.
# WRONG
class Order(models.Model):
ordered_by = models.ForeignKey(
Customer, on_delete=models.CASCADE, related_name="ordered_by")
# RIGHT
class Order(models.Model):
ordered_by = models.ForeignKey(
Customer, on_delete=models.CASCADE, related_name="customer_who_ordered")
Use choices
whenever there is a list of values
When a field in a model is designed to have a limited set of choices (think of a dropdown as its corresponding widget in the UI), it's always a good idea to define choices for the field.
It makes the code more readable and easy to maintain when there is a need to modify the values for some business reason. Validation of the field is also quite straightforward when defined as a choice field.
Where to place the choices field is debatable ๐.
If there are a lot of such list values in your business scenario or if a particular type of value will appear in multiple tables/classes (example: gender field) then a probable case may be to have a separate choices.py
so that a particular choice field can be reused.
Otherwise, it's a good idea to just define it as the first thing in your class.
# WRONG
class Icecream(models.Model):
flavor = models.CharField("Choose your flavor", max_length=500, \
blank=False, null=False)
# RIGHT
class Icecream(models.Model):
flavor_choices = (
("butterscotch", "Butterscotch"),
("carmel", "Carmel"),
("pista", "Pista"),
("strawberry", "Strawberry"),
("vanilla", "Vanilla")
)
flavor = models.CharField("Choose your flavor", choices=flavor_choices,
default="vanilla")
Use indexes for frequently queried fields
There are a few fields that will be used in most of the queries, especially the unique fields in a table. For such cases, it helps by defining them as indexes as part of Meta
definition.
Let's assume in our ice cream shop website, email is the unique identifier for a customer. Hence all queries that fetch customer details, dashboard-related ones especially will use email as part of the where
clause. In such a case, we should define the index on the email
column.
# WRONG
class Customer(models.Model):
first_name = models.CharField("First name", ...)
last_name = models.CharField("Last name", ...)
email = models.EmailField("Email address", ...)
# RIGHT
class Customer(models.Model):
first_name = models.CharField("First name", ...)
last_name = models.CharField("Last name", ...)
email = models.EmailField("Email address", ...)
class Meta:
indexes = [
models.Index(fields=["email"]),
]
Will be continued
As I mentioned at the beginning of the post, I shall write a couple of posts in the immediate future concerning models
as it is the backbone of any Django application.
Hope you found them useful!