Photo by Christopher Gower on Unsplash
Introduction
Defining database models is the most critical part of a new project. Djangoโs coding style ives us a recommended way to create models for our apps which I only discovered today thanks to LearnDjango.๐ Creating database models may not be simple to devs who havenโt laid hands on Django yet, but Iโll try my best to make sense. ๐
Learn Django is one of my go-to resources in being a Django developer. If you havenโt checked out the article about my top Django resources, you can check it here.
Model and Field Names
Models will always start with a Capital letter and will always be singular because they should only represent a single object and be using underscores and not a camelCase.
from django.db import models
class City(models.Model):
town_name = models.CharField(max_length=50)
Common Methods
Defining models is not easy nor should not be difficult. Next we add the __str__
and get_absolute_url()
methods.
Defining the str
method makes the model human-readable in the Django admin.
Defining the get_absolute_url()
method tells Django how to calculate the canonical URL for the model. This method should return a string that references a view on the site. Itโs also a good practice to use get_absolute_url()
on the templates instead of hard-coding them.
<a href="town/{{ object.id }]}/">{{ object.town_name }}</a>
# wrong
<a href="{{ object.get_absolute_url }}/">{{ object.town_name }}</a>
# better
from django.db import models
from django.urls import reverse # new
class City(models.Model):
town_name = models.CharField(max_length=50)
def __str__(self): # new
return self.town_name
def get_absolute_url(self):
return reverse('town', kwargs={"town_name": self.town_name})
Explicit Naming
Explicit is better than implicit
There are two ways to implicitly set the human-readable name for each field which Django does by automatically converting underscores to spaces. One is to use verbose_name(); if the field type is not OneToOneField, ManyToMany or ForeignKey, you can set it as the first positional argument.
from django.db import models
class City(models.Model):
town_name = models.CharField(
max_length=50,
verbose_name='town name',
)
def __str__(self):
return self.town_name
def get_absolute_url(self):
return reverse('town', kwargs={"town_name": self.town_name})
If a model uses ForeignKey, the model will have access to a Manager that returns all instances of the first model. This model returns QuerySets which can be filtered to retrieve objects.
Example:
>>> a = City.objects.get()
...
class Mayor(models.Model):
first_name = models.CharField('first name', max_length=30)
last_name = models.CharField('last name', max_length=30)
city = models.ForeignKey(
City,
on_delete=models.CASCADE,
related_name='mayors',
related_query_name='human',
)
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
def get_absolute_url(self):
return reverse('town_mayor', kwargs={'town_name': self.town_name})
References
- Coding style | Django documentation | Django
- Django Best Practices: Models | LearnDjango
- Model instance reference | Django documentation | Django
- PEP 20 -- The Zen of Python | Python.org
- Making queries | Django documentation | Django
In [1]: from blog.source.models import Category
In [2]: a = Category.objects.get(name='python')
In [3]: print(a) python
Top comments (1)
Thanks for the detailed article on how to design better models in Django. These instructions really helped me improve my performance and organize my code more efficiently. Implementing Drift Boss Unblocked into my workflow is also a great way to ensure stability and maintainability for my project.