In web development, databases (also memory cache) are critical in managing data efficiently since their operations are implemented in well-considered data structures and algorithms (and other reasons).
Managing databases is a complex task.
Django simplifies it through the Object Relational Mapping ORM system. We don’t explicitly define SQL schemas for relational databases such as SQLite, PostgreSQL, or MySQL. Instead, the SQL schema is auto-generated by reading the model classes defined in models.py. This feature allows developers to focus more on coding in Python rather than managing SQL directly for most common works.
ORM is a common technique found in other places. While Django comes with its ORM, SQLAlchemy is another popular ORM used in the Python ecosystem.
Django ORM largely handles the common works to use RDBMS. It reduces the complexity of the project and lets coders to focus more on the native objects (Python Django or other similar counterparts) rather than SQL.
A Model (Python class) maps to a table of the database.
An example of a model class in Django:
from django.db import models
class ModelName(models.Model):
field1 = models.CharField(max_length=200, unique=True,)
field2 = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
Models.Field represents a database field which is a column in the database
table. In the example, CharField, TextField, and DateTimeField are Model.Field classes.max_length, auto_now_add are Field options. Not all of them are enforced by the database (side
effect inside the database), for example, unique_for_date is a validation constraint in Python.
The best reference goes to Django Models and FieldsModel classes can be related to each other. Multiple entries belong to an author while other entries belong to a different author. This is a one-to-many relationship.
A record of a User can be related to a record of a User Profile. This is a one-to-one relationship. While a post is being liked by multiple users, a user can like multiple posts. This is a many-to-many relationship.
In relational database design, Entity Relationship is an important process to design the database schema. Django ORM supports the following relationships:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Note queries hopping over foreign keys are not efficient. Frequent hits to the database are not
good for performance, consider using select_related or prefetch_related to reduce the number of
queries.
The composition concept in Object oriented programming applies for similar Models.
Meta programming is one of less mentioned features in Python. In Django, it is heavily used.
Children models stem from base Models.
Note the differences between the Proxy, Multi-table, and Abstract models.
Check Django Model Inheritance
QuerySet API is an important part of ORM to interact with the database with Python.
One doesn't want to call Python database libraries to interact with databases. The QuerySet API is
designed to interact with Django Model data.
It allows CRUD of a row, filtering, sorting, and other operations on the database.
Mostly what SQL can do, QuerySet is designed to do the same. But different databases have different
implementations and features. raw() allows SQL statements in Django ORM.
It is a big topic to cover. Here are some examples:
The shell command allows interacting with data directly from the command line so that one need not to
work on the admin site or database interfaces directly.
python manage.py shell # working directory located with manage.py
Inside the shell:
from myapp.models import BlogPost
BlogPost.objects.create(title='My First Post',
content='This is the content.')
post = BlogPost.objects.get(id=1)
post.title = 'Updated Title'
post.save()
post.delete()
# Many other complex operations that replace SQL statements
The "shell" is a good tool to test snippets and debug the code. It is good for testing models, integration with other non-Django packages and some small algorithms.
Form is an interface to facilitate data validation, template context rendered in HTML widgets, instances of Model classes, etc. Model Form is the type of form that manages the fields of the Model class automatically. Form API allows to logic data to/from the users to work correctly.
# forms.py:
from Django import forms
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
# views.py:
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid(): # validation
form.save()
return redirect('post-list')
return render(request, 'post_form.html', {'form': form})
A parallel component to Form is actually DRF (Django Rest Framework) which is a third-party
Django package. DRF is for RESTful APIs. Another competitor Ninja + Pydantic looks promising
too.
Form should be discussed individually.
Only a few common relational databases are supported by Django native ORM. SQLite is the default database. One may need to look up third-party packages or write custom to use other databases.
Migrating existing data to other databases is a complex task.
Migrations are a way to propagate changes you make to your models into your database schema. They are crucial for maintaining the integrity of your database.
# Creating Migration files
python manage.py makemigrations <app>
#Applying Migrations
python manage.py migrate
It involves two steps:
makemigrations create migration files in the migrations/ directory of the app. migrate
applies to the database.
Migration files are like 0001_initial.py, 0002_auto_20210101_0001.py. They are Python files
that keep track of proper schema changes. Sometimes, if not used properly, update conflicts occur.
ContentType, and Signals modules are also relevant to Model. They are for external Django app interpolations.
Also, remember to write tests on the models' behaviors. Testing allows the discovery of logic inconsistency when updating.
The Django Model is a huge topic. Understanding the interplay among ORM Querysets, Model declarations, Database operations, testing, and other components is crucial for a Django developer.