This article is participating in Python Theme Month. See the link for details

Rest cannot be enjoyed by lazy people.~

preface

Django view layer is mainly used to handle the request of the corresponding url and returns the response data, in the process of the request – response generally involves two points, the first is the view layer will interact and layer model (data), to add and delete data, the second is the view layer need to pass some data to the front-end HTML page. This article focuses on the first part of how the view layer interacts with the database.

Model layer function introduction

Djangos model layer’s main function is to interact with the database, using ORM(object relational mapping) easy to implement data add, delete, change and query operations, Django comes with a database sqlite3, but the database is not very sensitive to date format, processing error prone. Therefore, other databases, such as MySQL, are usually used within the Django framework.

Django to connect MySQL

Instead of using Django’s own SQlite3, use MySQL or some other relational database as follows:

The first step is to modify the database in Django’s settings.py configuration file.

# change before
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3'.'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),}}# modified
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql'.'NAME': 'practice'// MySQL library name'USER':'root'// MySQL user name'PASSWORD':'1026'// MySQL password'HOST':'127.0.0.1'// Address of the data'PORT':3306.'CHARSET':'utf8',}}Copy the code

The second step requires code declaration. In the __init__.py file of the same directory as your project, write the following code that tells Django to use Pymysql instead of the default mysqlDB.

# first_django/fist_django/__init__.py
import pymysql


pymysql.install_as_MySQLdb()
Copy the code

django ORM

You can manipulate a database by executing SQL statements in the Pymysql module, but writing SQL statements in Python feels strange…

Djangos ORM(Object relational Mapping) allows you to quickly manipulate a database using Python’s object-oriented code, but it also has the disadvantage of being too wrapped, and sometimes SQL statements are inefficient. ORM is an object-relational mapping (ORM).

Django ORM operates databases

The first step is to create a class under models.py, corresponding to the MySQL table, the class must inherit models.Model, each application uses the table to create the class.

from django.db import models
 
# Create your models here.
class Info(models.Model) :
    # id int primary key auto increment
    id = models.AutoField(primary_key=True,verbose_name=id)
    # username varchar(32)
    username = models.CharField(max_length=32, verbose_name = username)# password int
    password = models.IntegerField(verbose_name='password')
Copy the code

If you want to create the corresponding table in the database, you must execute the database migration command and modify the models.py code related to the database. There are two database migration commands:

Python Manage.py Makemigrations // Log data on a small book (migrations folder generates a file) Python Manage.py Migrate // Truly synchronize operations to the databaseCopy the code

Django ORM uses fields and field parameters

Let’s look at some commonly used fields first:

AutoField: intParameter Description Value Primary_key: Specifies whether to set the parameter to autoincrement. Set it toTrueThe fields are primary key columns IntegerField: integer type, no additional parameters are required CharField: string type must be supplied Max_length Parameter indicates the maximum length of the string to be received TextField: Large text type DateTimeField: indicates the time type. Auto_now: indicates the time typeTrueAuto_now_add: indicates the latest time when a record is modifiedTrueDateField: indicates the time type. Only the date, month, and year are displayed. Auto_now: indicates the time typeTrueAuto_now_add: indicates the latest time when a record is modifiedTrueThe current time will be automatically saved when new data is added. The data will not be modified in EmailField: string data in mailbox format. ImageField: image type upload_to: file image upload Server_only path width_field: BoolenField: Store Boolean values. Height_field: specifies the height of an image. FieldField: specifies the file type. Upload_to: specifies the path to upload a file to the serverCopy the code

The following are common arguments to fields:

Null: Indicates whether data is not null. The default value isFalseBlank: The default is blankFalseTo verify whether the form data is empty, which is recommendedTrueDefault: indicates the default value of database fields. Unique: indicates whether the data is unique. To: If models.DO_NOTHING = models.DO_NOTHING = models.DO_NOTHING = models.DO_NOTHING = models.DO_NOTHING When is equal to theTrueDb_index: specifies whether a column is an index. Db_column: Specifies the name of the column in the database. If this parameter is not set, the column in the database is the name of the attribute in the model. Gender_choice = ((0.'male'),
        	(1.'female'),
        	(2.'others')
    		)
    gender = models.IntegerField(choices=gender_choice, default=0) There are only three values for the gender field: 0,1, and 2. The default is 0Verbose_name: the name of the table field displayed in Django admin help_text: similar to remarksCopy the code

In addition, for some model-level configurations, such as table-level configurations, you can define a Meta class in the model and add attributes to this class to control other attributes of the table, such as synindexing, specifying the table name instead of using the model type:

class User(models.Model) :
    id = models.AutoField(primary_key=True, verbose_name='primary key')
    name = models.CharField(max_length=10, verbose_name='Username')
    age = models.IntegerField(verbose_name='age')
    
    class Meta:
        db_table = 'User table'   # specify table name instead of using class name User
        index_together = [(name, age)]  The # name age field is not necessarily unique in forming a federated index
        unique_together = [(name,age)]  # name age forms a joint unique index
Copy the code

Djangos ORM works with tables — add, delete, modify, and query a single table

Setting up the Test Environment

To create a test environment, you need to set up a test environment. In your Django application, you have a test.py file provided by Django. To build a test environment, you need to load the Django project configuration file. Only the django project configuration file loaded can be used. Write the following code in the test file to set up the test environment:

if __name__ == '__main__':
    import os
    import django

    os.environ.setdefault('DJANGO_SETTINGS_MODULE'.'first_django.settings')  # This line of code comes from manage.py- load configuration
    django.setup()
    Write the code to operate the database below, note the indentation oh ~
Copy the code

First create a table, based on this table to add, delete, change, check the basic operations:

# models.py
from django.db import models

class User(models.Model) :
    id = models.AutoField(primary_key=True)  Django will create the column automatically if it is not written, and the column name will be id
    username = models.CharField(max_length=8, verbose_name='Username')
    age = models.IntegerField(verbose_name='age')
    GENDER = (
        (0.'male'),
        (1.'female'),
        (2.'others')
    )
    gender = models.IntegerField(choices=GENDER, verbose_name='gender')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='Creation time')
    alter_time = models.DateTimeField(auto_now=True, verbose_name='Last modified time')
    
    def __str__(self) :
        return self.username
Copy the code

Don’t forget to execute database migration commands!

python manage.py makemigrations
python manage.py migrate
Copy the code

SQL > create table (); create table (); create table ();

mysql> use practice;
Database changed
mysql> show tables;
+----------------------------+
| Tables_in_practice         |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| first_user                 |
+----------------------------+
11 rows in set (0.00 sec)
Copy the code

Basic data increase, delete, change and check

Now you can add, delete, and query data in test.py. It is important to mention that when writing orM statements, when using the primary key field as the query condition, no matter what the primary key field name is, pk can be used instead.

# test.py

if __name__ == '__main__':
    import os
    import django

    os.environ.setdefault('DJANGO_SETTINGS_MODULE'.'first_django.settings')
    django.setup()

    from first import models

    Create is used to add data
    user_info = {
        'username': 'python'.'age': 10.'gender': 0,
    }
    user_obj = models.User.objects.create(**user_info)  # return the object of User
    # also can be written as user_obj = models. User. Objects. The create (username = 'python', the age = 10, gender = 0)
    print(user_obj)

    # modify data
    # Change method 1, this method is recommended
    alter_info = {
        'username': 'java'
    }
    edit_obj = models.User.objects.filter(pk=1).update(**alter_info)
    print(edit_obj)

    This method is not recommended because it is inefficient when there are too many fields
    First, get the object to be modified, filter is used to filter data to get a list-like structure
    edit_obj = models.User.objects.filter(id=1).first()  #.first() just need the first data
    # ② Use objects. Property to modify,
    edit_obj.username = alter_info['username']
    edit_obj.save()  # Don't forget to save
    
    # delete data
    # batch delete
    res = models.User.objects.filter(username='python').delete()
    # single delete
    res = models.User.objects.filter(pk=1).first().delete()
    
   Select * from 'filter'; select * from 'filter'
    # select * from single data
    user_obj = models.User.objects.filter(username='java', the age =5)
    print(user_obj)  # 
      
       ]> get a QuerySet object. Index values are supported but not recommended
      
    print(user_obj.first())  # Java gets objects
    # query all data
    user_objs = models.User.objects.all(a)print(user_objs)  # <QuerySet [<User: java>, <User: python>]>
Copy the code

View the SQL corresponding to the ORM statement

If you want to view the corresponding SQL statements of ORM statements, there are two ways:

Query returns the SQL statement corresponding to the ORM statement of the QuerySet
user_objs = models.User.objects.all(a)print(user_objs.query)

Method 2: All SQL statements can be viewed, which needs to be configured in the configuration file. When the return value of the ORM statement is printed, the corresponding SQL statement is directly displayed
Add the following code to the configuration file
LOGGING = {
    'version': 1.'disable_existing_loggers': False.'handlers': {
        'console': {'level':'DEBUG'.'class':'logging.StreamHandler',}},'loggers': {
        'django.db.backends': {
            'handlers': ['console'].'propagate': True.'level':'DEBUG',}}}Copy the code

ORM statement other methods

All of the above add, delete, alter, and query operations are single-table operations. In addition to the above methods, there are other methods that only QuerySet objects can call. :

Last (): The last object in querySet values('username'Select username, age; select username, agefromuser; < querySet [{querySet [{querySet [{'username': 'python'}, {'username': 'python'}, {'username': 'python'}, {'username': 'python'}]>
    
value_list('username'< querySet [() < querySet [() < querySet [()'python',), ('python',), ('python',), ('python',)] > distinct () : to restore operation, to weight must be the same data, if with a primary key to weight, certain to go to such as: models. The User objects. Values ('name'.'age'). Distinct order_by () () : sorting operation, the default is ascending, add - before ordering rules is descending models. The User objects. Order_by ('age') 
models.User.objects.order_by('-age') reverse () : reverse operation, inversion is the premise of data have been row preface, must follow after order_by models. The User objects. Order_by ('name'). The reverse () the count () : statistical quantity res = models. User. Objects. The count () exclude () : exclude a particular data res = models. User. Objects. Exclude (name ='java')
print(res) exists(): it is not used to determine whether a data exists, because the data itself has a Boolean value and returns a Boolean value res = models.user.objects.filter(pk=2).exists()
print(res)
Copy the code

Query data – double underline

When querying data, many times the filter conditions are not =, there are many filter conditions are >=,<=,<,> and fuzzy query, interval query, etc., so how to query these? A lot of people think, why not use >=,<=,<,>? It makes it clear that the django ORM filter does not support writing these symbols directly, but uses the magic double underscore method instead. Double underline can be found in filter()

In the implementation of magic operation, flexible implementation of data filtering query, basic syntax filter(field name __ method), the following example to illustrate the use of double underline:

# greater than: __gt
models.User.objects.filter(age__gt=3)  # filter age > 3

# < : __lt
models.User.objdects.filter(age__lt=3)  # filter age < 3

# greater than or equal to: __gte
models.User.objdects.filter(age__gte=3)  # filter age >=3

Less than or equal to: __lte
models.User.objdects.filter(age__lte=3)  # filter age <=3

# Interval filtering
models.User.objects.filter(age__in[1.2.3])  # Age is one of them
models.User.objects.filter(age_range=[1.10])  # Two years between 1 and 10, including the beginning and end

# fuzzy query
models.User.objects.filter(name__contains='p')  # case sensitive names containing p
models.User.objects.filter(name__icontains='p')  # case insensitive, the name contains p
models.User.objects.filter(name__startswith='p')  # names that begin with P
models.User.objects.filter(name__endswith='a')  # Names ending in a

# time query
models.User.objects.filter(register_time__year='2021')  The date is 2021
models.User.objects.filter(register_time__month='7')  # It was in July
models.User.objects.filter(register_time__day='21')  # It's on the 21st
Copy the code

The article is not over

Djangos model layer is a little bit more knowledgeable. The previous section covers single-table operations

conclusion

This article was first published on the wechat public account ** “Cheng Xuyuan Xiaozhuang” **, and also on the nuggets.

The code word is not easy, reprint please explain the source, pass by the little friends of the lovely little finger point like and then go (╹▽╹)