How to save, fetch, and update data in Django Database
For every web application, you must store data, whether files or the database, to achieve full web application functionality. Every web technology has its approach to defining how data is stored and structured.
I have always used Django for most of my projects.
Django is a very robust web framework that
- Allows you to create smart websites easily,
- Define the implementation of the structure and storage for your data,
- Connect to popular relational databases easily, among many other features.
Among the robust features offered by Django is the Django models.
What are Django models?
A model class in Django is used to define the representation of data of your Django application.
The model class inherits the Model class that helps you define the entities and properties for the data used in your web applications.
These records remain persistent in a relational database.
A relational database such as PostgreSQL or MySQL will store the entities and properties in rows and columns, with each model in your Django application having its table.
Which database is best for Django?
The preferred database for Django is PostgreSQL because it is more robust and stable compared to other database management systems such as MySQL and Oracle. Moreover, PostgreSQL is an object-relational database making it the most suitable for storing geographical data.
Why we use models in Django
Django models are the Python objects you use to define how data will be stored, accessed, and managed in the database.
In short, a model in Django contains all the information about the essential fields and behaviors of the data you’re storing in the database.
With models, you can define the fields, field data types, data storage structure, and behavior of retrieving the data, among many other options that Django provides.
Your Django application will require a way to store and retrieve data in the database.
Django models enables you to define the fields to store in your database tables, the data type for each field e.g integers or strings, length of characters accepted in each field, define if a field is required or not, among many other options.
Django uses the Object-Relational Mapper whenever you call a model object, which creates correct statements for each object.
The generated SQL queries are then executed to create corresponding tables, rows, and columns in your relational database.
The process of creating tables, rows, columns, and records in the database using Django models
The process of writing a Django model and creating persistent data in the databases involves:
Step 1: Define a model that inherits the models.Model class using Python code.
from django.db import models
# Create your models here.
class BlogPost(models.Model):
...
Step 2: Define the fields required for each model object and their data types
from django.db import models
# Create your models here.
class BlogPost(models.Model):
# define your fields here
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
Step 3: Define the behavior of the fields using the Meta class. For example, define how to retrieve data in a way that is sorted from the latest to the earliest object.
from django.db import models
# Create your models here.
class BlogPost(models.Model):
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
# start with inner class and the additional functions
class Meta:
verbose_name_plural = 'Blog Posts'
# Order the blog posts in reverse starting from the latest to the earliest
ordering = ('-published_on', )
def __str__(self):
return self.post_title
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('blogpost_detail', kwargs=kwargs)
Step 4: Run the python manage.py makemigrations
command to create SQL statements
Open the Terminal, activate the virtual environment for your project, and type the following command:
python manage.py makemigrations
Step 5: Run the python manage.py migrate
to execute the generated SQL statements and create persistent tables.
python manage.py makemigrations
Step 6: Instantiate the model object while providing the appropriate fields as the arguments and call the save() method to create a record in the database.
Within the steps, I have introduced two new Django commands: makemigrations
and migrate
.
What is the difference between makemigrations and migrate as used in Django?
makemigrations (python manage,py makemigrations ) | migrate (python manage,py migrate ) |
makemigrations command is used to create the necessary SQL commands | migrate command is used to execute the generated SQL commands |
Run makemigrations after changing the model fields, e.g., adding a field, editing a field, or deleting a model. | Run migrate command when you have generated migrations using the makemigrations command. |
makemigrations command does not create persistent records in the relational database | migrate command creates persistent/permanent changes to the database. |
How Django models operate
Django models use the Django ORM as the primary approach to writing database functionalities.
What is Django ORM?
Django ORM in full means Object Relational Mapper.
Django ORM enables you to retrieve or manipulate data stored in the database as if using SQL queries.
Django ORM is implemented using a Pythonic way that allows you to create SQL query statements using Python code.
The generated SQL queries are then used to query and manipulate the database and produce results.
In this approach, however, you do not see much of the SQL queries being done to your database as a developer.
You may use tools such as the Django Debug Toolbar package, navigate into the SQL queries section, and be able to see SQL statements executed on the database.
Django ORM is necessary because you will create a complex web application and work with a relational database such as PostgreSQL.
Django ORM is a very powerful tool that you may use to write queries made to the database easily.
The Object-Relational Mapper (ORM) helps you interact with the web application data from the relational database used in your Django application.
The relational database may not only be PostgreSQL but also may be MySQL, SQLite, MariaDB, or Oracle.
Advantages of Django ORM
- Drastic improvement in development time
- ORMs work very well with CRUD applications such as Django web apps
- Django ORM allows the writing of correct SQL queries
- Django ORM helps write optimized SQL queries
- Make code easier to update, maintain, and reuse
- Speeds up the development process
Django Model Fields and Django models data types
Django model fields are the data types used to store data in the database.
Django uses model fields to determine the column type of the database where it can be INTEGER, VARCHAR, TEXT, e.t.c
Django supports different model data types that include but are not limited to:
- Integer data are declared in a model using AutoField, BigAutoField, and Big IntegerField.
- Raw binary data declared in a model using BinaryField,
- Boolean data is expressed in the model using BooleanField.
- String data that is declared using CharField and TextField.
- The date that may be declared using DateField and DateTimeField
- Fixed-precision decimal numbers are expressed using DecimalField.
- Periods of time that may be declared using DurationField.
- Emails are declared using the EmailField field.
- A file upload is declared using FileField.
Follow this link to check Django documentation that contains a list of all model data types and fields.
More information about some of the fields used in Django models:
The difference between CharField and TextField in Django
CharField is a string field for storing small and large strings for your Django model objects, while TextField is a string field designed to hold very large string characters.
models.CharField | models.TextField |
CharField is used to store shorter-length string characters | TextField is used to store very large string characters. |
CharField is ideal for storing string characters less than 255 characters | TexField is ideal for storing string characters of more than 255 characters |
Use CharField to store shorter strings such as user’s names, city, postal addresses, e.t.c | Use TextField to store longer strings such as blog post content |
For example, you would use CharField to store a blog post title, a user’s first name, e.t.c.
A standard parameter you may supply to the CharField or TextField is the max_length.
What is max_length in Django?
max_length is used to limit the number of characters a CharField, SlugField, or TextField may accept.
You may use the max_length parameter to limit users from entering more than 200 characters for their first name.
Moreover, when you have a contact page, users do not need to send you a novel or a story.
You may limit them to a certain number of characters whenever they send you a message.
What is a primary key in Django?
The primary key in Django is an automatically added id field that is added to each model.
Every time you create a new model object, Django automatically adds an id field that is used to identify an object uniquely.
No two model objects can have the same id or primary key.
You may also create a custom primary key field for your Django models by providing an extra keyword to the field.
Django uses the new primary key field without creating the default primary key.
The difference between ForeignKey and primary key in Django
ForeignKey (models.ForeignKey ) | Primary Key |
ForeignKey provides a link between data in two different tables. A column (model field) links to data in another table. For example, you will use the category model to associate a blog post using a foreign key field. | Ensures each model object has unique data. The id is usually used as a primary key, but you may define a custom primary key field. |
Stored as a ForeignKeyField in Django | Stored as an IntegerField in Django as default |
Used for linking two different tables in the database | Used for uniquely identifying a record in the database |
What is the difference between null and blank in Django?
null | blank |
Null informs the database whether a field should have a value or not | Blank informs a user whether a field should have a value or not on a form |
Applicable when validating values stored in the Django database | Applicable when validating Django forms |
Null sets the value of a column NULL or NOT NULL | Blank sets a form field to be required (must have a value) or not required (can leave a field empty) |
Null is purely database-related | Blank is purely validation-related |
In most scenarios, you will have to use the two values when creating Django models because when you set a field to be blank, you must also set the corresponding field to accept NULL value in the database.
When you set null=False blank=False, Django expects the associated fields have a value in all circumstances: in the Django form and the database.
When you set null=True and blank=True, Django validates the associated fields as optional in both Django forms and database columns.
Null = True means that a string-based field will have an empty string.
The field will not have ‘NULL’ in the database but will have a real value that happens to be a value containing 0 characters.
auto_now and auto_now_add as used in Django
To set automatic dates when saving or updating data in your database, you use Django DateTime and Date fields that accept two arguments, namely auto_now and auto_now_add.
The two arguments are booleans values when they can be set to True or False to accept automatic dates.
The two arguments differentiate from each other in the following ways:
auto_now (models.DateTimeField(auto_now=True) ) | auto_now_add (models.DateTimeField(auto_now_add=True) ) |
auto_now sets the time only when you update a field in your database. If you change the content or featured image of your blog posts, the auto_now_add will update to the time you changed your blog post fields. | auto_now_add Will set the time only when an instance is created. Let’s say you create a blog post on your Django website the first time; auto_now will be used. |
Updates a value of a DateField to the current time and date every time the model.save() method is called. | Updates the value of a field to the first time and date the model.save() is called. |
Functions and Classes used with Django class models
Common functions used with Django model class:
- __str__() function,
- get_absolute_url() function
Typical class used with Django model class:
- Class Meta
Django models Meta class
What is meta class in Django models?
Class Meta, a Python class, is an optional inner class defined in your model class.
The meta class is used to change various options for the model fields, such as how the objects are ordered and the plural name of an object field, among many other behaviors.
Let’s say you have a Category model class in your Django models.
class Category(models.Model):
title = models.CharField(max_length=50)
In this case, Django will return the model’s plural name as categorys, which is incorrect, on the admin page.
To change the category plural name, you would use the class meta to change that.
Here’s how you would do it:
class Category(models.Model):
title = models.CharField(max_length=50)
class Meta:
verbose_name_plural = 'categories'
Now, if I look at the admin page, the category model admin should show categories instead of categorys.
There are other incredible options that you may use in your Django class meta, such as changing the order of your objects in the admin page and templates.
For example, here’s how to order your blog posts based on the published date:
class BlogPost(models.Model):
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = 'Blog Posts'
# Order the blog posts in reverse
# starting from the latest to the earliest
ordering = ('-published_on', )
Django models __str__() function
The __str__() method displays more user-friendly object names in the Django admin site page and templates.
When you create a class that inherits models.Model class, you create a Python object.
For example:
class BlogPost(models.Model):
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
Here, we are creating a blog post object that has a title, slug, meta description, and content fields.
Every time you call the class, an object instance will be created for each blog post item.
So, you have blogpost1, blogpost2, blogpost3, and so on, with each blogpost object having different values for id, title, slug, meta description, and content.
Django returns the blogpost object every time you call but will not show you the title of each blog post object.
Let me show you what I mean.
If I register the BlogPost model to the admin module, I should be able to see the blog post objects in the admin area.
In my blog/admin.py file, I have added the following lines to register the BlogPost model to the admin area:
from django.contrib import admin
# Register your models here.
from .models import BlogPost
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
pass
When I open the admin page and create a few blog posts, here is what I see:
See, Django does not show us the titles of our two blog posts.
But instead, return blogpost objects.
Instead of the BlogPost object(1), we use the __str__() method to show a more user-friendly name.
Here’s how you would do it:
Open your models.py file and add the __str__() method to define how Django will display the blog post objects.
class BlogPost(models.Model):
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
def __str__(self):
return self.post_title
After adding the __str__() method, the admin page will show a more descriptive name for our blog post objects.
See the image below.
That is how the __str__ method works in Python Django.
Django models get_absolute_url() function
What is get_absolute_url in Django models?
get_absolute_url() is another optional function that you may use to define canonical URLs whenever you display your objects on web pages.
Canonical URLs are mostly used in Search Engine Optimization to avoid duplicate pages or indexed pages that do not match the right URL.
Let’s say you have a Django application with various blog post objects.
You will need to display each blog post object using its URL.
However, you will end up having more than two URLs for each blog post.
What do I mean,
Let’s say the default URL for the first blog post is example.com/blog/first-post.
However, if I have search functionality in my Django web application and search the keyword ‘first-post’, Django will automatically redirect me to example.com?blog=first-post.
The two URLs link to the same resource, the blog post with the title first-post.
Search engines use the canonical URL for each blog post resource.
Search engines use one version of a URL (canonical URL) for indexing your site’s resources when different URL versions are used in a web application.
Therefore, use canonical URLs to improve your website’s SEO because search engines prefer them as they provide user-friendly and descriptive URLs for your Django web pages.
For our Django blog application, here’s how you would implement SEO-friendly canonical URLs using the get_absolute_url() function.
class BlogPost(models.Model):
post_title = models.CharField(max_length=90)
slug = models.SlugField(max_length=90)
meta_description = models.CharField(max_length=1000)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = 'Blog Posts'
# Order the blog posts in reverse
# starting from the latest to the earliest
ordering = ('-published_on', )
def __str__(self):
return self.post_title
# new lines of code
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('blogpost_detail', kwargs=kwargs)
The only field I have added to our Django application is the SlugField, which stores URL slugs for each blog post object.
What is a slug field in Django?
Django slug fields are used to generate valid URLs in a dynamic approach.
Slug field in Django models helps create and store dynamically generated valid URLs for each web page in your Django application.
The common application of the slug field is in creating dynamic URLs for blog post objects created in your Django application.
For a URL to be valid, it must not have spaces, new lines, tabs, carriage, “, <, >, ^, `, {, |, }.
Django slugs help remove such characters when we may accidentally use them in our pages or blog posts’ titles.
Instead, slug fields replace such characters with – to provide valid and SEO-friendly URLs for our web pages.
So, in the code above, I have used the slug field in the get_absolute_url as the valid canonical URL that search engines will use to index the dynamically generated blog post web pages.
Conclusion
Pheew!
…
See how easy it is to create tables and records in your Django relational databases.
See you next time, Dev!