django advanced more: https://docs.djangoproject.com/en/3.0/

Posted by Dakkar on Tue, 03 Mar 2020 08:46:59 +0100

Model

ORM (relationship object mapping)

1. field

    AutoField(Field)
        # int Auto increment column, parameter must be filled primary_key=True

    BigAutoField(AutoField)
        # bigint Auto increment column, parameter must be filled primary_key=True

       //If there is no auto increment column in the model, a column named id will be created automatically
        from django.db import models

        class UserInfo(models.Model):
            # Automatically create a column named id And is an increasing integer column
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # Custom Auto increment column
            nid = models.AutoField(primary_key=True)
Self increasing field
    SmallIntegerField(IntegerField):
        # Small integer -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        # Positive small integer 0 ~ 32767

    IntegerField(Field)
        # Integer column(Signed) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        # Positive integer 0 ~ 2147483647

    BigIntegerField(IntegerField):
        # Long integer(Signed) -9223372036854775808 ~ 9223372036854775807

    # Custom unsigned integer field
        class UnsignedIntegerField(models.IntegerField):
            def db_type(self, connection):
                return 'integer UNSIGNED'
Integer field
    BooleanField(Field)
        # Boolean type

    NullBooleanField(Field):
        # Boolean value that can be empty

    CharField(Field)
        # Character type
        # Must provide max_length Parameters, max_length Represents character length

    TextField(Field)
        # Text type

    EmailField(CharField): 
        # String type, Django Admin as well as ModelForm Authentication mechanism provided in

    IPAddressField(Field)
        # String type, Django Admin as well as ModelForm Validation provided in IPV4 mechanism

    GenericIPAddressField(Field)
        # String type, Django Admin as well as ModelForm Validation provided in Ipv4 and Ipv6
        # Parameters:
            protocol,Used for designation Ipv4 or Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, If specified as True,Then input.::ffff:192.0.2.1 It can be resolved to 192.0.2.1,To enable the stab function, you need to protocol="both"

    URLField(CharField)
        # String type, Django Admin as well as ModelForm Validation provided in URL

    SlugField(CharField)
        # String type, Django Admin as well as ModelForm Letters, numbers, underscores, connectors (minus signs) are supported for validation

    CommaSeparatedIntegerField(CharField)
        # String type, the format must be a comma separated number

    UUIDField(Field)
        # String type, Django Admin as well as ModelForm Provided in pairs UUID Format validation

    FilePathField(Field)
        # Character string, Django Admin as well as ModelForm The function of reading files under folders is provided in
        # Parameters:
                path,                      Folder path
                match=None,                Regular matching
                recursive=False,           Recurse the folder below
                allow_files=True,          Allow file
                allow_folders=False,       Allow folders

    FileField(Field)
        # String, path saved in database, file uploaded to specified directory
        # Parameters:
            upload_to = ""      Save path of uploaded file
            storage = None      Storage components, default django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        # String, path saved in database, file uploaded to specified directory
        # Parameters:
            upload_to = ""      Save path of uploaded file
            storage = None      Storage components, default django.core.files.storage.FileSystemStorage
            width_field=None,   Highly saved database field name (string) of uploaded image
            height_field=None   Width of uploaded image saved database field name (string)

    DateTimeField(DateField)
        # date+Time format YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        # Date format      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        # Time format      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        # Long integer, time interval, according to bigint Storage, ORM The value obtained in is datetime.timedelta type

    FloatField(Field)
        # float

    DecimalField(Field)
        # 10 Binary decimal system
        # Parameters:
            max_digits,Total decimal length
            decimal_places,Decimal length

    BinaryField(Field)
        # Binary type
Other fields
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
The return value is the property of the field in the database, and the default value of Django field
    null                Whether the field in the database can be empty
    db_column           Column name of the field in the database
    db_tablespace
    default             Default values for fields in the database
    primary_key         Whether the fields in the database are primary keys
    db_index            Whether fields in the database can be indexed
    unique              Whether fields in the database can be uniquely indexed
    unique_for_date     Can a unique index be created for the date part of the field in the database
    unique_for_month    Can a unique index be created for the [month] part of the field in the database
    unique_for_year     Can a unique index be created for the year part of the field in the database

    verbose_name        Admin Field name shown in
    blank               Admin Allow user input to be blank in
    editable            Admin Whether it can be edited in
    help_text           Admin Prompt for this field in
    choices             Admin The contents of the selection box are displayed in, and unchanging data is placed in memory to avoid cross table operation
                        //Such as: gf = models.IntegerField(choices=[(0, 'xx'),(1, 'xxx'),],default=1)

    error_messages      Customize the error information (Dictionary type), so as to customize the error information to be displayed;
                        //Dictionary key: null, blank, invalid, invalid_choice, unique, and unique_for_date
                        //{'null': "Can not be empty.", 'invalid': 'Format error'}

    validators          Customize error validation (list type) to customize the validation rules you want
                        from django.core.validators import RegexValidator
                        from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
                        MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                        //Such as:
                            test = models.CharField(
                                max_length=32,
                                error_messages={
                                    'c1': 'Priority error message 1',
                                    'c2': 'Priority error message 2',
                                    'c3': 'Priority error message 3',
                                },
                                validators=[
                                    RegexValidator(regex='root_\d+', message='Wrong.', code='c1'),
                                    RegexValidator(regex='root_112233\d+', message='Wrong again.', code='c2'),
                                    EmailValidator(message='Wrong again.', code='c3'), ]
parameter
            # Table names generated in the database default app Name + Underline + Class name
            db_table = "table_name"

            # Joint index
            index_together = [
                ("pub_date", "deadline"),
            ]

            # Union unique index
            unique_together = (("driver", "restaurant"),)

            # admin Table name shown in
            verbose_name

            # verbose_name plus s
            verbose_name_plural
        
    //More: https://docs.djangoproject.com/en/1.10/ref/models/options/
class Meta:
        a. Django Admin The error messages in will take precedence according to Admiin Internal ModelForm Error message prompt, if all succeed, check Model And displays the specified error message
        b. call Model Object clean_fields Methods, such as:
            # models.py
            class UserInfo(models.Model):
                nid = models.AutoField(primary_key=True)
                username = models.CharField(max_length=32)

                email = models.EmailField(error_messages={'invalid': 'The format is wrong..'})

            # views.py
            def index(request):
                obj = models.UserInfo(username='11234', email='uu')
                try:
                    print(obj.clean_fields())
                except Exception as e:
                    print(e)
                return HttpResponse('ok')

           # Model Of clean Method is a hook that can be used for custom operations, such as exception handling above.
Trigger validation and error prompts in the Model
        # admin.py
        from django.contrib import admin
        from model_club import models
        from django import forms


        class UserInfoForm(forms.ModelForm):
            username = forms.CharField(error_messages={'required': 'User name cannot be empty.'})
            email = forms.EmailField(error_messages={'invalid': 'Mailbox format error.'})
            age = forms.IntegerField(initial=1, error_messages={'required': 'Please enter a value.', 'invalid': 'Age must be numeric.'})

            class Meta:
                model = models.UserInfo
                # fields = ('username',)
                fields = "__all__"


        class UserInfoAdmin(admin.ModelAdmin):
            form = UserInfoForm


        admin.site.register(models.UserInfo, UserInfoAdmin)
Modify error prompt in admin

2. continuous tables

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # Table name to associate
        to_field=None,              # Field name in the table to associate
        on_delete=None,             # The behavior of the current table and its associated rows when data in the associated table is deleted
                                        - models.CASCADE,Delete associated data and associated data
                                        - models.DO_NOTHING,Delete associated data, error raised IntegrityError
                                        - models.PROTECT,Delete associated data, error raised ProtectedError
                                        - models.SET_NULL,Delete the associated data with the value set to null(premise FK Field needs to be set to nullable)
                                        - models.SET_DEFAULT,Delete the associated data, and set the value associated with it to the default value (premise FK Field needs to set default value)
                                        - models.SET,Delete associated data,
                                                      a. The associated value is set to the specified value, setting: models.SET(value)
                                                      b. The value associated with it is set to the return value of the executable object. Set: models.SET(Executable object)

                                                        def func():
                                                            return 10

                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # In reverse operation, the field name is used instead of table name_set] Such as: obj.Table name_set.all()
        related_query_name=None,    # In reverse operation, the connection prefix is used to replace table name     Such as: models.UserGroup.objects.filter(Table name__Field name=1).values('Table name__Field name')
        limit_choices_to=None,      # stay Admin or ModelForm When the associated data is displayed in, the following conditions are provided:
                                    # Such as:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        db_constraint=True          # Whether to create a foreign key constraint in the database
        parent_link=False           # stay Admin Show associated data in


    OneToOneField(ForeignKey)
        to,                         # Table name to associate
        to_field=None               # Field name in the table to associate
        on_delete=None,             # The behavior of the current table and its associated rows when data in the associated table is deleted

                                    ###### For one-on-one ######
                                    # 1. One to one is actually one to many + unique index
                                    # 2.When there is an inheritance relationship between two classes, a one-to-one field will be created by default
                                    # The following will be A Add an additional one to the table c_ptr_id Column and unique:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)

                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

    ManyToManyField(RelatedField)
        to,                         # Table name to associate
        related_name=None,          # In reverse operation, the field name is used instead of table name_set] Such as: obj.Table name_set.all()
        related_query_name=None,    # In reverse operation, the connection prefix is used to replace table name     Such as: models.UserGroup.objects.filter(Table name__Field name=1).values('Table name__Field name')
        limit_choices_to=None,      # stay Admin or ModelForm When the associated data is displayed in, the following conditions are provided:
                                    # Such as:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # For many to many self association only, symmetrical A field that specifies whether a reverse operation is created internally
                                    # When doing the following operations, the symmetrical There will be different optional fields
                                        models.BB.objects.filter(...)

                                        # The optional fields are: code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=True)

                                        # Optional fields are: bb, code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=False)

        through=None,               # Use fields to specify relational tables when customizing the third table
        through_fields=None,        # When customizing the third table, use fields to specify which fields in the relationship table are used for many to many relationship tables
                                        from django.db import models

                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)

                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through='Membership',
                                                through_fields=('group', 'person'),
                                            )

                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # Whether to create a foreign key constraint in the database
        db_table=None,              # The name of the table in the database when the third table is created by default
Fields, parameters

3. operation

    # increase
    # models.Tb1.objects.create(c1='xx', c2='oo')  Add a piece of data to accept dictionary type data **kwargs

    # obj = models.Tb1(c1='xx', c2='oo')
    # obj.save()

    # check
    # models.Tb1.objects.get(id=123)         # Get a single piece of data and report an error if it does not exist (not recommended)
    # models.Tb1.objects.all()               # Get all
    # models.Tb1.objects.filter(name='seven') # Get data for the specified condition

    # Delete
    # models.Tb1.objects.filter(name='seven').delete() # Delete data for specified conditions

    # change
    # models.Tb1.objects.filter(name='seven').update(gender='0')  # Update the data of the specified conditions, all of which support * * kwargs
    # obj = models.Tb1.objects.get(id=1)
    # obj.c1 = '111'
    # obj.save()                                                 # Modify single data
basic operation
        # Get number
        #
        # models.Tb1.objects.filter(name='seven').count()

        # Greater than, less than
        #
        # models.Tb1.objects.filter(id__gt=1)              # Get a value with id greater than 1
        # models.Tb1.objects.filter(id__gte=1)              # Get a value with id greater than or equal to 1
        # models.Tb1.objects.filter(id__lt=10)             # Get a value with id less than 10
        # models.Tb1.objects.filter(id__lte=10)             # Get a value with id less than 10
        # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # Get a value with id greater than 1 and less than 10

        # in
        #
        # models.Tb1.objects.filter(id__in=[11, 22, 33])   # Get data with id equal to 11, 22, 33
        # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

        # isnull
        # Entry.objects.filter(pub_date__isnull=True)

        # contains
        #
        # models.Tb1.objects.filter(name__contains="ven")
        # models.Tb1.objects.filter(name__icontains="ven") # icontains case insensitive
        # models.Tb1.objects.exclude(name__icontains="ven")

        # range
        #
        # models.Tb1.objects.filter(id__range=[1, 2])   # Range between and

        # Other similar
        #
        # startswith,istartswith, endswith, iendswith,

        # order by
        #
        # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
        # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc

        # group by
        #
        # from django.db.models import Count, Min, Max, Sum
        # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
        # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

        # limit ,offset
        #
        # models.Tb1.objects.all()[10:20]

        # regex Regular matching, iregex Case insensitive
        #
        # Entry.objects.get(title__regex=r'^(An?|The) +')
        # Entry.objects.get(title__iregex=r'^(an?|the) +')

        # date
        #
        # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
        # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

        # year
        #
        # Entry.objects.filter(pub_date__year=2005)
        # Entry.objects.filter(pub_date__year__gte=2005)

        # month
        #
        # Entry.objects.filter(pub_date__month=12)
        # Entry.objects.filter(pub_date__month__gte=6)

        # day
        #
        # Entry.objects.filter(pub_date__day=3)
        # Entry.objects.filter(pub_date__day__gte=3)

        # week_day
        #
        # Entry.objects.filter(pub_date__week_day=2)
        # Entry.objects.filter(pub_date__week_day__gte=2)

        # hour
        #
        # Event.objects.filter(timestamp__hour=23)
        # Event.objects.filter(time__hour=5)
        # Event.objects.filter(timestamp__hour__gte=12)

        # minute
        #
        # Event.objects.filter(timestamp__minute=29)
        # Event.objects.filter(time__minute=46)
        # Event.objects.filter(timestamp__minute__gte=29)

        # second
        #
        # Event.objects.filter(timestamp__second=31)
        # Event.objects.filter(time__second=2)
        # Event.objects.filter(timestamp__second__gte=31)
Advanced operation (double underline)
    # extra
    #
    # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    #    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
    #    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    #    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    #    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

    # F
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


    # Q
    #
    # Method 1:
    # Q(nid__gt=10)
    # Q(nid=8) | Q(nid__gt=10)
    # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
    # Mode two:
    # con = Q()
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 10))
    # q1.children.append(('id', 9))
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('c1', 1))
    # q2.children.append(('c1', 10))
    # q2.children.append(('c1', 9))
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)


    # Execution primordial SQL
    #
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections['default'].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()
extra,F,Q,python native sql
# Table structure instance   oto and fk Medium demand addition on_delete The code above the parameter contains
class UserProfile(models.Model):
    user_info = models.OneToOneField('UserInfo',on_delete=models.CASCADE)
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __str__(self):
        return self.username


class UserInfo(models.Model):
    user_type_choice = (
        (0, u'Ordinary users'),
        (1, u'Advanced user'),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __str__(self):
        return self.name


class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField('UserInfo')

    def __str__(self):
        return self.caption


class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey('UserGroup',on_delete=models.CASCADE)

    def __str__(self):
        return self.hostname
Table structure
#o2o


user_info_obj = models.UserInfo.objects.filter(id=1).first()
print user_info_obj.user_type
print user_info_obj.get_user_type_display()
print user_info_obj.userprofile.password
 
user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
print user_info_obj.keys()
print user_info_obj.values()


#m2o



//Similar to one-on-one
1,Search criteria use __ Connect
2,Use when getting values .    Connect




#m2m
user_info_obj = models.UserInfo.objects.get(name='xxx')
user_info_objs = models.UserInfo.objects.all()
 
group_obj = models.UserGroup.objects.get(caption='xxxx')
group_objs = models.UserGroup.objects.all()
 
# Add data
#group_obj.user_info.add(user_info_obj)
#group_obj.user_info.add(*user_info_objs)
 
# Delete data
#group_obj.user_info.remove(user_info_obj)
#group_obj.user_info.remove(*user_info_objs)
 
# Add data
#user_info_obj.usergroup_set.add(group_obj)
#user_info_obj.usergroup_set.add(*group_objs)
 
# Delete data
#user_info_obj.usergroup_set.remove(group_obj)
#user_info_obj.usergroup_set.remove(*group_objs)
 
# get data
#print group_obj.user_info.all()
#print group_obj.user_info.all().filter(id=1)
 
# get data
#print user_info_obj.usergroup_set.all()
#print user_info_obj.usergroup_set.all().filter(caption='CEO')
#print user_info_obj.usergroup_set.all().filter(caption='DBA')
Linked list

form

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError


def mobile_validate(value):
    mobile_re = re.compile('^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('Mobile number format error')


class PublishForm(forms.Form):

    user_type_choice = (
        (0, 'Ordinary users'),
        (1, 'Advanced user'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': 'Title cannot be empty',
                                            'min_length': 'The title must be at least 5 characters',
                                            'max_length': 'Title up to 20 characters'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': 'Heading 5-20 Character'}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': 'Detailed description', 'rows': 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': 'Mobile phone cannot be empty'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': 'Phone number'}))

    email = forms.EmailField(required=False,
                            error_messages={'required': 'Mailbox cannot be empty','invalid': 'Mailbox format error'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': 'mailbox'}))
Define form form
def publish(request):
    ret = {'status': False, 'data': '', 'error': '', 'summary': ''}
    if request.method == 'POST':
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print(request_dict)
            ret['status'] = True
        else:
            error_msg = request_form.errors.as_json()
            #as_ul(),  as_text()
            ret['error'] = json.loads(error_msg)
    return HttpResponse(json.dumps(ret))    
views verification
class AdminModelForm(forms.ModelForm):
      
    class Meta:
        model = models.Admin
        #fields = '__all__'
        fields = ('username', 'email')
          
        widgets = {
            'email' : forms.PasswordInput(attrs={'class':"xxx"}),
        }
modelform validation

Cross-site request forgery

Django implements the function of preventing cross Site Request Forgery for users through middleware django.middleware.csrf.CsrfViewMiddleware. The anti Cross Station Request Forgery function in Django can be divided into global and local.

Overall situation:

Middleware django.middleware.csrf.csfviewmiddleware

Part:

from django.views.decorators.csrf import csrf_exempt,csrf_protect

veiws Set the return value in:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
     //perhaps
     return render(request, 'xxx.html', data)
  
html Set in Token:
  {% csrf_token %}
General form
# Establish js Document, following

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        let cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            let cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
let csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});



# Use ajax
<script src='Above file name xxx.js'></script>
<script>
.....
</script>
ajax

more:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

Cookies and session s

Acquisition of Chinese Medicine
request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    Parameters:
        Default: default
           Salt: salt addition
        Max? Age: background control expiration time

Setting up
 rep = HttpResponse(...) or rep = render(request,...)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt = 'encrypted salt',...)
    Parameters:
        Key, key
        Value = '', value
        max_age=None, timeout
        expires=None, timeout (ie requires expires, so set it if has't been already ready.)
        Path = '/', the path where the cookie takes effect, / indicates the root path, special: the cookie following the path can be accessed by any url page
        Domain = none, the domain name in which the cookie takes effect
        Secure = false, HTTPS transport
        httponly=False can only be transmitted by http protocol and cannot be obtained by JavaScript (not absolute, the underlying packet grabbing can be obtained or overwritten)

#The cookie is saved on the client side. The native js and jQuery are operable
<script src='/static/js/jquery-3.4.1.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });
cookie
'''
Django Default support in Session,There are five types of Session For developers:

//Database (default)
//cache
//file
//Cache + Database
//Encrypted cookie
'''


# data base session
Django Default support Session,And the default is Session Data is stored in the database, that is: django_session In the table.
 
a. To configure settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # Engine (default)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session Of cookie When saved on the browser key,Namely: sessionid=Random string (default)
    SESSION_COOKIE_PATH = "/"                               # Session Of cookie Saved path (default)
    SESSION_COOKIE_DOMAIN = None                             # Session Of cookie Saved domain name (default)
    SESSION_COOKIE_SECURE = False                            # Whether Https transmission cookie(Default)
    SESSION_COOKIE_HTTPONLY = True                           # Whether Session Of cookie Only support http Transfer (default)
    SESSION_COOKIE_AGE = 1209600                             # Session Of cookie Expiration date (2 weeks) (default)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # Whether to close the browser Session Expiration (default)
    SESSION_SAVE_EVERY_REQUEST = False                       # Save every request Session,Save after default modification (default)
 
 
 
b. Use
 
    def index(request):
        # Get, set, delete Session Middle data
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # Do not set if it exists
        del request.session['k1']
 
        # All key, value, key value pairs
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # user session Random string of
        request.session.session_key
 
        # Will all Session Delete data with expiration date less than current date
        request.session.clear_expired()
 
        # Check users session Is the random string of
        request.session.exists("session_key")
 
        # Delete all of the current user's Session data
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * If value It's an integer, session It will expire in a few seconds.
            * If value It's a datatime or timedelta,session It will expire after this time.
            * If value It's 0.,User closes browser session It will fail.
            * If value yes None,session Will depend on the overall situation session Failure strategy.


# cache session
a. To configure settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # engine
    SESSION_CACHE_ALIAS = 'default'                            # Cache alias used (default memory cache, or memcache),Alias depends on cached settings here
 
 
    SESSION_COOKIE_NAME = "sessionid"                        # Session Of cookie When saved on the browser key,Namely: sessionid=Random string
    SESSION_COOKIE_PATH = "/"                                # Session Of cookie Saved path
    SESSION_COOKIE_DOMAIN = None                              # Session Of cookie Saved domain name
    SESSION_COOKIE_SECURE = False                             # Whether Https transmission cookie
    SESSION_COOKIE_HTTPONLY = True                            # Whether Session Of cookie Only support http transmission
    SESSION_COOKIE_AGE = 1209600                              # Session Of cookie Expiration date (2 weeks)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # Whether to close the browser Session Be overdue
    SESSION_SAVE_EVERY_REQUEST = False                        # Save every request Session,Save only after default modification
 
 
 
b. Use
 
    //Ditto



# file session
a. To configure settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # engine
    SESSION_FILE_PATH = None                                    # Cache file path, if None,Then use tempfile Module gets a temporary address tempfile.gettempdir()                                                            # For example, / var / folders / D3 / j9tj0gz93dg06bmwxmhh6 xm0000gn / T
 
 
    SESSION_COOKIE_NAME = "sessionid"                          # Session Of cookie When saved on the browser key,Namely: sessionid=Random string
    SESSION_COOKIE_PATH = "/"                                  # Session Of cookie Saved path
    SESSION_COOKIE_DOMAIN = None                                # Session Of cookie Saved domain name
    SESSION_COOKIE_SECURE = False                               # Whether Https transmission cookie
    SESSION_COOKIE_HTTPONLY = True                              # Whether Session Of cookie Only support http transmission
    SESSION_COOKIE_AGE = 1209600                                # Session Of cookie Expiration date (2 weeks)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # Whether to close the browser Session Be overdue
    SESSION_SAVE_EVERY_REQUEST = False                          # Save every request Session,Save only after default modification
 
b. Use
 
    //Ditto



# cache+data base session
Database is used for persistence and cache is used for efficiency improvement
 
a. To configure settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # engine
 
b. Use
 
    //Ditto

# encryption cookie 
a. To configure settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # engine
 
b. Use
 
    //Ditto




# session User authentication decorator
def login(func):
    def wrap(request, *args, **kwargs):
        # If not logged in, jump to the specified page
        if request.path == '/test/':
            return redirect('http://xxxxxxxxxxxx')
        return func(request, *args, **kwargs)
    return wrap
session

paging

# version 1
views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')

    paginator = Paginator(L, 10)
    # per_page: Number of entries per page
    # count:    Total number of data
    # num_pages:PageCount
    # page_range:Index range of total pages, such as: (1,10),(1,200)
    # page:     page object
    try:
        posts = paginator.page(current_page)
        # has_next              Is there a next page
        # next_page_number      Next page
        # has_previous          Is there a previous page
        # previous_page_number  Previous page
        # object_list           List of data after paging
        # number                Current page
        # paginator             paginator object
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})



HTML

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
      <span class="step-links">
        {% if posts.has_previous %}
            <a href="?p={{ posts.previous_page_number }}">Previous</a>
        {% endif %}
          <span class="current">
            Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
          </span>
          {% if posts.has_next %}
              <a href="?p={{ posts.next_page_number }}">Next</a>
          {% endif %}
      </span>

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



#version 2
views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        """
        :param current_page: Current page
        :param max_pager_num:Maximum number of pages displayed
        :param args:
        :param kwargs:
        :return:
        """
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def page_num_range(self):
        # Current page
        # self.current_page
        # PageCount
        # self.num_pages
        # Maximum number of pages displayed
        # self.max_pager_num
        print(1)
        if self.num_pages < self.max_pager_num:
            return range(1, self.num_pages + 1)
        print(2)
        part = int(self.max_pager_num / 2)
        if self.current_page - part < 1:
            return range(1, self.max_pager_num + 1)
        print(3)
        if self.current_page + part > self.num_pages:
            return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
        print(4)
        return range(self.current_page - part, self.current_page + part + 1)


L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page, 11, L, 10)
    # per_page: Number of entries per page
    # count:    Total number of data
    # num_pages:PageCount
    # page_range:Index range of total pages, such as: (1,10),(1,200)
    # page:     page object
    try:
        posts = paginator.page(current_page)
        # has_next              Is there a next page
        # next_page_number      Next page
        # has_previous          Is there a previous page
        # previous_page_number  Previous page
        # object_list           List of data after paging
        # number                Current page
        # paginator             paginator object
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request, 'index.html', {'posts': posts})


HTML

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
<span class="step-links">
{% if posts.has_previous %}
    <a href="?p={{ posts.previous_page_number }}">Previous</a>
{% endif %}

    {% for i in posts.paginator.page_num_range %}
        <a href="?p={{ i }}">{{ i }}</a>
    {% endfor %}

    {% if posts.has_next %}
        <a href="?p={{ posts.next_page_number }}">Next</a>
    {% endif %}
</span>

<span class="current">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
</span>

</div>
</body>
</html>
Built-in paging
'''
//Paging function is necessary in every website. For paging, it is actually to calculate the starting position in the database table according to the user's input.

1,Set the number of data displayed per page
2,User input page number (Page 1, page 2...)
3,Calculate the starting position of the data table to be fetched according to the set number of displayed items and the current page number
4,In the data table, the value is taken according to the starting position, and the data is output on the page

//The demand is coming again. You need to display the paged page on the page. If: [previous] [1] [2] [3] [4] [5] [next]

1,Set the number of data displayed per page
2,User input page number (Page 1, page 2...)
3,Set how many page numbers are displayed
4,Get the total number of current data
5,Calculate the total number of pages according to the number of pages displayed and the total number of data
6,Calculate the starting position of the data table to be fetched according to the set number of displayed items and the current page number
7,In the data table, the value is taken according to the starting position, and the data is output on the page
8,Output paging html,Such as:[Previous page][1][2][3][4][5][next page]
'''



#!/usr/bin/env python
# _*_coding:utf-8_*_
from django.utils.safestring import mark_safe
 
class PageInfo(object):
    def __init__(self,current,totalItem,peritems=5):
        self.__current=current
        self.__peritems=peritems
        self.__totalItem=totalItem
    def From(self):
        return (self.__current-1)*self.__peritems
    def To(self):
        return self.__current*self.__peritems
    def TotalPage(self):  #PageCount
        result=divmod(self.__totalItem,self.__peritems)
        if result[1]==0:
            return result[0]
        else:
            return result[0]+1
 
def Custompager(baseurl,currentPage,totalpage):  #Base page, current page, total pages
    perPager=11
    #PageCount<11
    #0 -- totalpage
    #PageCount>11
        #Current page is greater than 5 currentPage-5 -- currentPage+5
            #currentPage+5 Whether the total number of pages is exceeded,More than total pages, end Is the total number of pages
        #Current page is less than 50 -- 11
    begin=0
    end=0
    if totalpage <= 11:
        begin=0
        end=totalpage
    else:
        if currentPage>5:
            begin=currentPage-5
            end=currentPage+5
            if end > totalpage:
                end=totalpage
        else:
            begin=0
            end=11
    pager_list=[]
    if currentPage<=1:
        first="<a href=''>home page</a>"
    else:
        first="<a href='%s%d'>home page</a>" % (baseurl,1)
    pager_list.append(first)
 
    if currentPage<=1:
        prev="<a href=''>Previous page</a>"
    else:
        prev="<a href='%s%d'>Previous page</a>" % (baseurl,currentPage-1)
    pager_list.append(prev)
 
    for i in range(begin+1,end+1):
        if i == currentPage:
            temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
        else:
            temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
        pager_list.append(temp)
    if currentPage>=totalpage:
        next="<a href='#'>next page</a>"
    else:
        next="<a href='%s%d'>next page</a>" % (baseurl,currentPage+1)
    pager_list.append(next)
    if currentPage>=totalpage:
        last="<a href=''>Last</a>"
    else:
        last="<a href='%s%d'>Last</a>" % (baseurl,totalpage)
    pager_list.append(last)
    result=''.join(pager_list)
    return mark_safe(result)   #Convert string to html language




'''
//In summary, there are three things to do when paging:

//Create a class to process paging data
//Get data from paging data
//Output page HTML, that is: [previous] [1] [2] [3] [4] [5] [next]
'''
custom

There are many plug-ins on the Internet. Search them out and have a look

cache

As Django is a dynamic website, all requests will go to the data for corresponding operations. When the program has a large amount of visits, the time-consuming will be more obvious. The simplest solution is to use: cache, which saves the return value of a certain view to memory or memcache. When someone comes to visit in 5 minutes, the operation in view will not be performed, but directly from the The previously cached content in the stored or Redis is retrieved and returned.

There are six caching methods available in Django:

    # This is the start of commissioning. No internal operation is required
    # To configure:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # engine
                'TIMEOUT': 300,                                               # Cache timeout (default 300, None Indicates never expires, 0 indicates immediate expiration)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # Maximum number of caches (300 by default)
                    'CULL_FREQUENCY': 3,                                      # After the maximum number of caches is reached, the proportion of the number of caches to be eliminated is: 1/CULL_FREQUENCY(Default 3)
                },
                'KEY_PREFIX': '',                                             # cache key Prefix for (default empty)
                'VERSION': 1,                                                 # cache key Version of (default 1)
                'KEY_FUNCTION' Function name                                          # generate key Function of (the default function will be generated as::Edition:key])
            }
        }


    # custom key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.

        Constructs the key used by all other methods. By default it prepends
        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return '%s:%s:%s' % (key_prefix, version, key)

    def get_key_func(key_func):
        """
        Function to decide which key function to use.

        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func
Development and commissioning
    # This cache saves content to variables in memory
    # To configure:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

    # Other configurations are the same as the development debugging version
Memory
    # This cache saves content to a file
    # To configure:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': '/var/tmp/django_cache',
            }
        }
    # Other configurations are the same as the development debugging version
file
    # This cache saves content to the database

    # To configure:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                'LOCATION': 'my_cache_table', # Database table
            }
        }

    # Execute create table command python manage.py createcachetable
data base
# This cache uses python-memcached Module connection memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }
Memcache cache (Python memcached module)
    # This cache uses pylibmc Module connection memcache
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }
Memcache cache (pylibmc module)
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}
            # "PASSWORD": "Password",
        }
    }
}
Redis cache (dependency: PIP3 install Django redis)
from django_redis import get_redis_connection
conn = get_redis_connection("default")
Connection operation in views
#Total station
   Use middleware, through a series of authentication and other operations, if the content exists in the cache, use FetchFromCacheMiddleware Get the content and return it to the user. Before returning it to the user, judge whether the cache already exists. If not, then UpdateCacheMiddleware The cache will be saved to the cache to realize the whole site cache

    MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',
        # Other Middleware ...
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]

    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""

#Separate view
    Method 1:
        from django.views.decorators.cache import cache_page

        @cache_page(60 * 15)
        def my_view(request):
            ...

    //Mode two:
        from django.views.decorators.cache import cache_page

        urlpatterns = [
            url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
        ]

#Partial view
    a. Introduce TemplateTag

        {% load cache %}

    b. Using caching

        {% cache 5000 cache key %}
            //Cache content
        {% endcache %}
application

serialize

'''
//The serialization in Django is mainly used to return the data retrieved in the database to the client user, and the special Ajax request is usually returned in Json format.
'''

# serializers
from django.core import serializers
 
ret = models.BookType.objects.all()
 
data = serializers.serialize("json", ret)


# json.dumps
import json
 
#ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption')
 
ret=list(ret)
 
result = json.dumps(ret)



'''
//Because the datetime date cannot be processed in json.dumps, you can extend it by customizing the processor
'''

import json 
from datetime import date 
from datetime import datetime 
   
class JsonCustomEncoder(json.JSONEncoder): 
    
    def default(self, field): 
     
        if isinstance(field, datetime): 
            return o.strftime('%Y-%m-%d %H:%M:%S') 
        elif isinstance(field, date): 
            return o.strftime('%Y-%m-%d') 
        else: 
            return json.JSONEncoder.default(self, field) 
   
   
# ds = json.dumps(d, cls=JsonCustomEncoder) 

signal

Django provides "signal scheduling" for decoupling when the framework performs operations. Generally speaking, when some actions occur, the signal allows the specific sender to remind some receivers.

Model signals
    pre_init                    # django Of modal Trigger automatically before executing its construction method
    post_init                   # django Of modal Triggered automatically after execution of its construction method
    pre_save                    # django Of modal Automatically triggered before saving an object
    post_save                   # django Of modal Automatically triggered when an object is saved
    pre_delete                  # django Of modal Auto trigger before object deletion
    post_delete                 # django Of modal Triggered automatically when an object is deleted
    m2m_changed                 # django Of modal Use in m2m Third table of field operation( add,remove,clear)Front and rear, automatic trigger
    class_prepared              # Detect registered app in modal Class, for each class, auto trigger
Management signals
    pre_migrate                 # implement migrate Auto trigger before command
    post_migrate                # implement migrate Automatically triggered after command
Request/response signals
    request_started             # Auto trigger before request
    request_finished            # Auto trigger after request
    got_request_exception       # Automatically triggered after request exception
Test signals
    setting_changed             # Use test Triggered automatically when a profile is modified by a test
    template_rendered           # Use test Automatically triggered when testing a render template
Database Wrappers
    connection_created          # Automatically triggered when creating a database connection
Built-in signal
#about Django The built-in signal only needs to register the specified signal. When the program performs the corresponding operation, the registration function will be triggered automatically


    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed
    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created


    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)

    xxoo.connect(callback)
    # xxoo Refers to the content imported above





from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")
Use built-in signal
# Definition
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])


# register
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
 
pizza_done.connect(callback)



# trigger
from Route import pizza_done
 
pizza_done.send(sender='seven',toppings=123, size=456)

# Because the trigger of the built-in signal has been integrated into Django , so it will be called automatically, and for the custom signal, the developer needs to trigger it anywhere.
Custom signal

Topics: Python Django Session Database JSON