django thirty-three-[one-to-many] complete business operations corresponding to the table relationship

1. The purpose of writing this blog

Main record:

  1. How to create a [one-to-many] table relationship through django;
  2. And how to go through the corresponding complete business operations through the [one-to-many] table relationship;
  3. By modifying which code configuration in django, when the data in the [one] table is deleted, what changes will be made to the data in the corresponding [multi] table? 

Suppose there is a data table A and a data table B , then only one of the four table relationships may exist between table A and table B :

  1. Table A and Table B are independent;
  2. Table A and Table B have a one-to-many relationship. The value of a table field in Table B stores the primary key value of Table A;
  3. Table A and Table B have a one-to-one relationship. In Table B, the value of a table field stores the primary key value of Table A;
  4. Table A and Table B have a many-to-many relationship. The two table fields of an intermediate table store the primary key value of Table A and the primary key value of Table B respectively;

2. [One-to-many] Business example corresponding to table relationship

We will encounter many one-to-many scenarios in real life.

For example, one of the most common examples is: when we fill in the bank card information, we will select the corresponding bank information from the drop-down box of the submission field [Bank];

Generally, two data tables will be built, one for bank information, and one for bank card information;

Each bank can correspond to multiple bank cards, and each bank card can only belong to one bank;

Then the bank and the bank card have a one-to-many relationship, on the contrary, the bank card and the bank have a many-to-one relationship;

The complete operation process can be seen in the following content;

 

Three, the complete operation process

1. The first step: Add a model class in [ helloworld/hello/models.py ]

class Bank(models.Model):

    # 银行信息

    bank_name = models.CharField(max_length=50, verbose_name="银行名称")

    city = models.CharField(max_length=30, verbose_name="所在城市")

    point = models.CharField(max_length=60, verbose_name="所在网点")



    class Meta:

        verbose_name_plural = "银行"



    def __str__(self):

        return self.bank_name





class CardInfo(models.Model):

    # 银行卡信息

    card_id = models.CharField(max_length=30, verbose_name="卡号")

    card_name = models.CharField(max_length=10, verbose_name="姓名")

    card_info = models.ForeignKey(to=Bank, on_delete=models.CASCADE, verbose_name="选择银行")



    class Meta:

        verbose_name_plural = '银行卡信息'



    def __str__(self):

        return self.card_id

2. Step 2: Register the model class in [ helloworld/hello/admin.py ]

# 银行信息

class ControlBank(admin.ModelAdmin):

    list_display = ["id", "bank_name", "city", "point"]





# 银行卡信息

class ControlCardInfo(admin.ModelAdmin):

    list_display = ["id", "card_id", "card_name", "card_info"]





admin.site.register(models.Bank, ControlBank)

admin.site.register(models.CardInfo, ControlCardInfo)

 

3. The third step: execute the relevant statements to generate the data table in the root directory of [ helloworld/ ]

The relevant statements and order of execution are:

     3.1. First, execute the statement [python manage.py makemigrations]

     3.2. Finally, execute the statement [python manage.py migrate]

 The relevant results are as follows:

           Two corresponding data tables will be generated

 

 

 

4. Step 4 : Restart the service

5. Step 5 : Successfully log in to the admin management background

6. Step 6 : Add 2 bank information in the background

 

7. Step Seven: New in the background 1 bank card information

 

 

Four, related knowledge points

1. A simple analysis of the two required parameters in the class ForeignKey corresponding to the input parameter values

detail:

      From the class name of the class ForeignKey, we can intuitively know that the Chinese meaning of the word ForeignKey is [foreign key];

1.1. The first step: Look at the content in the [ __init__ ] method in the foreignKey source code

class ForeignKey(ForeignObject):

    """

    Provide a many-to-one relation by adding a column to the local model

    to hold the remote value.



    By default ForeignKey will target the pk of the remote model but this

    behavior can be changed by using the ``to_field`` argument.

    """

    descriptor_class = ForeignKeyDeferredAttribute

    # Field flags

    many_to_many = False

    many_to_one = True

    one_to_many = False

    one_to_one = False



    rel_class = ManyToOneRel



    empty_strings_allowed = False

    default_error_messages = {

        'invalid': _('%(model)s instance with %(field)s %(value)r does not exist.')

    }

    description = _("Foreign Key (type determined by related field)")



    def __init__(self, to, on_delete, related_name=None, related_query_name=None,

                 limit_choices_to=None, parent_link=False, to_field=None,

                 db_constraint=True, **kwargs):

        try:

            to._meta.model_name

        except AttributeError:

            assert isinstance(to, str), (

                "%s(%r) is invalid. First parameter to ForeignKey must be "

                "either a model, a model name, or the string %r" % (

                    self.__class__.__name__, to,

                    RECURSIVE_RELATIONSHIP_CONSTANT,

                )

            )

        else:

            # For backwards compatibility purposes, we need to *try* and set

            # the to_field during FK construction. It won't be guaranteed to

            # be correct until contribute_to_class is called. Refs #12190.

            to_field = to_field or (to._meta.pk and to._meta.pk.name)

        if not callable(on_delete):

            raise TypeError('on_delete must be callable.')



        kwargs['rel'] = self.rel_class(

            self, to, to_field,

            related_name=related_name,

            related_query_name=related_query_name,

            limit_choices_to=limit_choices_to,

            parent_link=parent_link,

            on_delete=on_delete,

        )

        kwargs.setdefault('db_index', True)



        super().__init__(

            to,

            on_delete,

            from_fields=[RECURSIVE_RELATIONSHIP_CONSTANT],

            to_fields=[to_field],

            **kwargs,

        )

        self.db_constraint = db_constraint

 

Intercept this part of the source code:

    def __init__(self, to, on_delete, related_name=None, related_query_name=None,

                 limit_choices_to=None, parent_link=False, to_field=None,

                 db_constraint=True, **kwargs):

It can be easily seen from this part of the source code: when the class ForeignKey is instantiated, the two required parameters [ to ] and [ on_delete ] must be assigned respectively, and the input parameter values ​​of other input parameters generally keep the default values;

2. Step 2: Analyze the parameter value of the required parameter [ to ] and the parameter value of the required parameter [ on_delete ] based on the actual business code

The actual business code is as follows:

class Bank(models.Model):

    '''银行信息'''

    bank_name = models.CharField(max_length=50,verbose_name="银行名称")

    city = models.CharField(max_length=30,verbose_name="所在城市")

    point = models.CharField(max_length=60,verbose_name="所在网点")



    class Meta:

        verbose_name_plural = "银行"



    def __str__(self):

        return self.bank_name





class CardInfo(models.Model):

    '''银行卡信息'''

    card_id = models.CharField(max_length=30, verbose_name="卡号")

    card_name = models.CharField(max_length=10, verbose_name="姓名")

    card_info = models.ForeignKey(to=Bank,on_delete=models.CASCADE,verbose_name="选择银行",)



    class Meta:

       verbose_name_plural = '银行卡信息'



    def __str__(self):

        return self.card_id

 

Intercept this part of the business code:

card_info = models.ForeignKey(to=Bank,on_delete=models.CASCADE,verbose_name="选择银行",)

3. Understanding of the parameter value of the required parameter [ to ]

The meaning of the parameter [ to ] is: related to a corresponding table ( this table is a one-to-many table in a one-to-many table relationship ) ;

The parameter value of the parameter [ to ]: it must only be the model class name of the model class corresponding to the [one in the one-to-many table relationship] model class;

4. Understanding of the parameter value of the required parameter [ on_delete ]

The meaning of the parameter [ on_delete ] is: the table relationship associated with the class ForeignKey is one-to-many two tables, when the table data of the one table is physically deleted, the table of the multi-table is physically deleted with these Corresponding changes will occur to the table data associated with the deleted table data;

The parameter value of the parameter [ on_delete ] must be only one of these 6 parameter values:

models.CASCADE
models.PROTECT
models.SET_NULL
models.SET_DEFAULT
moels.SET(value)
models.DO_NOTHING

detail:

  •  When the value of the parameter [on_delete] is [models.SET_NULL]: the value of the input parameter null in the class ForeignKey must be set to [True];
  •  When the value of the parameter [on_delete] is [models.SET_DEFAULT]: the input parameter value of the input parameter default in the class ForeignKey must be filled in and the input parameter value can only be a positive integer;
  •  When the value of the parameter [on_delete] is [models.SET(value)]: the input parameter value of the input parameter value in the method set() must be filled in and the input parameter value can only be a positive integer;
  •  The value of the parameter [on_delete] is [models.CASCADE], which is a frequently used scene;

 

Suppose that the bank shows such a piece of data ( we named this piece of data data A for the convenience of the description of the relevant copywriting later ) :

 

 Suppose that cardinfo shows two pieces of data ( we named these two pieces of data as data B and data C , respectively , to facilitate the description of related copywriting later ) :

 

 

 

The specific functions of each parameter value are as follows:

models.CASCADE : In admin management background, when the data A are deleted physically, with the data A associated data B and data C will also be physically removed;

models.PROTECT : In the admin management background, when data A is to be physically deleted, it will be prompted to physically delete data B and data C before physically deleting data A , and then try to physically delete data after physically deleting data B and data C successfully At A , data A can be physically deleted immediately ;

models.SET_NULL : In the admin management background, when data A is physically deleted, the values of the table fields [ card_info_id ] of data B and data C associated with data A will change from [ 25 ] to [ Null ];

models.SET_DEFAULT : In the admin management background, when data A is physically deleted, the value of the table field [ card_info_id ] of data B and data C associated with data A will change from [ 25 ] to the input parameter default in the class ForeignKey The input parameter value ( the input parameter value of the default parameter can only be a positive integer ) ;

moels.SET : In the admin management background, when data A is physically deleted, the value of the table field [ card_info_id ] of data B and data C associated with data A will change from [ 25 ] to the entry in the method set() The input parameter value of the parameter value ( the input parameter value of the input parameter value can only be a positive integer ) ;

models.DO_NOTHING : In the admin management background, when data A is physically deleted, the table field value of each table field of data B and data C associated with data A remains unchanged ( that is, after data A is physically deleted, Data B and Data C are not affected at all ) ;

 

The specific business codes corresponding to these 6 parameter values ​​are as follows ( I have debugged them locally ) :

    card_info = models.ForeignKey(to=Bank,on_delete=models.CASCADE,verbose_name="选择银行",)

    card_info = models.ForeignKey(to=Bank,on_delete=models.PROTECT,verbose_name="选择银行",)

    card_info = models.ForeignKey(to=Bank,on_delete=models.SET_NULL,verbose_name="选择银行",null=True)

    card_info = models.ForeignKey(to=Bank,on_delete=models.SET_DEFAULT,verbose_name="选择银行",default=999999999)

    card_info = models.ForeignKey(to=Bank,on_delete=models.SET(value=7777777),verbose_name="选择银行",)

    card_info = models.ForeignKey(to=Bank,on_delete=models.DO_NOTHING,verbose_name="选择银行",)

 

 

 

Guess you like

Origin blog.csdn.net/LYX_WIN/article/details/114997261