Django ORM-based CURD, foreign key association, request life cycle

Article directory

  • CURD based on ORM
  • ORM foreign key association
  • Django request life cycle flow chart

CURD based on ORM

In essence, it is to add, delete, modify and check the data in the database through object-oriented method.

Here we will combine all our previous content together. First, make sure that the UserInfo table has been created based on the previous operation. Then we also need to create several HTML files. Only focus on the tags related to submitted data

user_list: used as homepage

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2" >

                <h1 class="text-center">User list display</h1>
                
                <a href="/add/" class="btn btn-info" >Add</a>
                <table class="table table-striped table-bordered">
                    <thread>
                        <tr>
                            <th class="text-center">ID</th>
                            <th class="text-center">username</th>
                            <th class="text-center">password</th>
                            <th class="text-center">gender</th>
                            <th class="text-center">action</th>
                        </tr>
                    </thread>
                    <tbody>
                        {<!-- -->% for foo in user_obj %}
                        <tr>
                            <td class="text-center" >{<!-- -->{<!-- --> foo.id }}</td>
                            <td class="text-center" >{<!-- -->{<!-- --> foo.username }}</td>
                            <td class="text-center" >{<!-- -->{<!-- --> foo.password }}</td>
                            <td class="text-center" >{<!-- -->{<!-- --> foo.gender }}</td>
                            <td>
                                <a href="/edit/?id={<!-- -->{ foo.id }}" class="btn btn-success" style="margin-left: 65px;" >Modify</a> & amp;nbsp; & amp;nbsp;
                                <a href="/delete/?id={<!-- -->{ foo.pk }}" class="btn btn-danger ">Delete</a>
                            </td>
                        </tr>
                        {<!-- -->% endfor %}

                    </tbody>
                </table>

            </div>
        </div>
    </div>
</body>
</html>

The homepage has been created, now we need to configure the routing file urls.py. Configure routing according to the page jumped by clicking the button on the home page.

The routing file urls.py is configured as follows:

If the front-end and back-end are not developed by the same person, these URLs must be specified in advance.
View functions for the homepage

add.html: Data page for adding new users

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">Add user</h1>
                
                <form action="" method="post">
                    <div class="form-group">
                        username: <input type="text" class="form-control" name="username" placeholder="Please enter username">
                    </div>

                    <div class="form-group">
                        password: <input type="password" class="form-control" name="password" placeholder="Please enter password">
                    </div>

                    <div class="form-group">
                        gender: <input type="text" class="form-control" name="gender" placeholder="Please enter gender">
                    </div>

                    <div class="form-group">
                        <input type="submit" class="btn btn-block btn-success" value="submit">
                    </div>

                </form>

            </div>
        </div>
    </div>
</body>
</html>

According to the action of the form above, we can see that the data is submitted to submit post request in place.

The add page view function is as follows:

 def add(request):
    if request.method == 'POST': # Receive post requests sent by users to add data
        username = request.POST.get('username')
        password = request.POST.get('password')
        gender = request.POST.get('gender')
\t\t
'Add data to the database'
'Operation database to add data'
        add_obj=models.UserInfo.objects.create(username=username, password=password, gender=gender)
        'Returns the object of the current record'
# print(add_obj) # jack
# print(add_obj.gender) # male
\t\t
        return redirect('/user_list/') #Redirect to home page

    return render(request, 'add.html', locals())

When the post request data is submitted in place, it will be received by our current view function and then written to the database.

At this point we can click the Add button from the homepage, and then after completing the input, check the effect:

At this point, the effect of data synchronization to the web page has been achieved, so let’s try to modify it again.

edit.html: page for modifying data

<!DOCTYPE html>
<html lang="en">
<head>
    {<!-- -->% load static %}
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="//i2.wp.com/cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">Modify page</h1>
                
                <form action="" method="post">
                    <div class="form-group">
                        username: <input type="text" class="form-control" name="username" value="{<!-- -->{ edit_obj.username }}">
                    </div>
                    <div class="form-group">
                        password: <input type="password" class="form-control" name="password" value="{<!-- -->{ edit_obj.password }}">
                    </div>
                    <div class="form-group">
                        gender: <input type="text" class="form-control" name="gender" value="{<!-- -->{ edit_obj.gender }}">
                    </div>

                    <div class="form-group">
                        <input type="submit" class="btn btn-block btn-success" value="submit">
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
</html>

The routine of modifying the page is basically the same as adding the data page. Observe that the submission address of the form is the original address, and then receive the data on the backend based on the name attribute value of the input element.

Because we have defined it in the user_list page and click the modify button, the URL address will also carry a user id number, so we need to receive this number and modify the user information based on it.

 def edit(request):
    edit_id = request.GET.get('id') # GET can get the data after the question mark in the URL

    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        gender = request.POST.get('gender')
\t
'''Modify field syntax in database update userinfo set username='', password='' where id=1;'''
# The first way
models.UserInfo.objects.filter(pk=edit_id).update(username=username,password=password,gender=gender)
Using the update statement method does not require save.
\t
# The second way
edit_obj = models.UserInfo.objects.filter(id=edit_id).first() # Get this user object
edit_obj.username = username # Modify the name of this user
edit_obj.password = password # Modify the password of this user
edit_obj.gender = gender # Modify gender
edit_obj.save() # Save the modified data to the database
\t\t
        return redirect('/user_list/')
    return render(request, 'edit.html', locals())


Naturally, no page is needed for deletion. After clicking on the homepage, it will jump to a URL to execute a view function, and this URL carries the user’s number, so the basic operation routine is the same.

 def delete(request):
    del_id = request.GET.get('id')
    print(del_id)
    '''Syntax for deleting fields in the database delete from userinfo where id = 1;'''
    models.UserInfo.objects.filter(pk=del_id).delete() # Delete the user with the same number in the database as passed by the page

    return redirect('/user_list/') # Redirect to the homepage to achieve a refreshing effect


The effect we expected has been achieved. Click the delete button to delete the entire row of data.

Let’s summarize the content used in the previous sequence.

 1. Check
models.User.objects.filter(name=username, pwd=password)
How to get the object? You can use the first() method. If there is no value, it will return None. We can just judge if
\t\t
obj = User.object.get(id=edit_id) # Get a user object
print(obj.name) # Query the name value of this user
\t\t
2. increase
\t\tmethod one:
models.User.objects.create(name='jack',password=123)
# Write a record to the database, the name field value is jack, the password field value is 123
\t\tMethod Two:
obj = models.User(username=username,password=password,gender=gender)
        obj.save()
\t\t
3.Change
\t\tmethod one:
models.User.objects.filter(id=1).update(name='tom')
\t\tMethod Two:
obj = models.User.objects.filter(id=1).first()
obj.name = 'tom' # Modify the name attribute value of this user
obj.age = 18 # Modify the age attribute value of this user
obj.save() # Synchronize the modified attribute values to the database
\t\t
4.Delete
models.User.objects.filter(id=1).delete() # Delete this user in the database

5. Get all user objects
obj_all = User.object.all()
You can also use the method locals() to obtain all local variables.
\t\t
6. Get a specified object
obj = User.object.filter('id').first()
'Filter is analogous to the use of where in the database'

At this point, the basic operations have been completed. The data in the database can be manipulated in an object-oriented manner, but the premise is that the model class is an existing database table. If it does not exist, Django will help us create it automatically when we perform migration.

So what if we want to import an existing table into our model. So let’s find out!

Import an existing table

Operating the database in Django is through the classes in models.py, and we currently only know how to create database tables through it, but not how to use it to import tables that already exist in the database.

There are two ways:

  • Within the model, create class names and class attributes according to the complete data structure of the table. The overall code is as follows:
 class Book(models.Model):
    name = models.CharField(max_length=30, blank=True, null=True)
    price = models.FloatField(blank=True, null=True)
    author = models.CharField(max_length=20, blank=True, null=True)

    class Meta:
        db_table = 'book'

You will find that there is an extra Meta internal class. We will not delve into its function at the moment. Just know its function at this time: specify the database table name corresponding to the model class through the db_table attribute.

  • Lazy way: Use Django’s own command inspectdb to generate the table name in the database in the form above:

Why not perform the migration operation? Because we did not perform operations such as adding tables, adding or modifying fields to the model class.

ORM foreign key association

 Association types are mainly divided into three categories, the same as MySQL types
one to many
Foreign key fields are built on the multi side
many to many
The foreign key field is built in the third relational table
One to one
Foreign key fields are built in tables with high query frequency
\t\t
ORM
one to many
Foreign key fields are built on the multi side
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
\t\t   \t
many to many
Foreign key fields can be written directly in a table, and ORM will automatically create a third table for you.
authors = models.ManyToManyField(to='Authors')
One to one
Foreign key fields are built in tables with high query frequency
detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
 '''Django1.x version does not need to write cascade delete cascade update, 2.x requires it, here is 2.x display'''
class Book(models.Model):
title = models.CharField(max_length=32)
# Books and publishers are one-to-many Books are many
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
''' Cascade delete Note that the primary key does not need to be added by yourself ORM will automatically add '''
# Books and authors are many-to-many
authors = models.ManyToManyField(to='Authors')
\t
class Publish(models.Model):
pub_name = models.CharField(max_length=32)
\t\t
class Authors(models.Model):
name = models.CharField(max_length=32)
detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
\t\t
class AuthorDetail(models.Model):
phone = models.BigIntegerField()

Django request life cycle flow chart

 The life cycle of Django is the process from the user sending HTTP request data to the website response.
The entire process includes:
\t
The browser sends an HTTP request (through orm) MySI obtains data->wsgiref service>View layer one>Middleware->templates template layer
->Routing layer urls->View layer rendering->View layer views->Middleware smodels model layer->Response content to the browser>
\t
1. First, the user enters a URL in the browser and sends a reguest request with the GET method.
2. In Django, there is a method module wsgiref that encapsulates socket. The listening port accepts request requests and is initially encapsulated and sent to the middleware.
3. The middleware transmits it to the routing system for route distribution and matches the corresponding view function.
4. Transfer the request request to the views view function for logical processing.
5. Call the table object in models, get the data through ORM operation database, and at the same time go to the corresponding template in templates for rendering.
6. The response is transmitted to the middleware, processed in turn, and the response is displayed to the browser and displayed to the user.


The Web Server Gateway Interface (Python Web Server Gateway Interface, abbreviated as WSGI) is a simple and universal interface between a web server and a web application or framework defined for the Python language. Of course we can also call it: WSGI protocol

The wsgiref module is a service module developed by python based on the WSGI protocol. The amount of concurrency it supports is not high, but it is enough for our development environment. After the program is online, we can use other web services to improve the performance of the server we run the program on.