【问题标题】:How to add all foreign key relations in Django?如何在 Django 中添加所有外键关系?
【发布时间】:2018-09-17 00:23:29
【问题描述】:

我有这两个模型:

class Country(models.Model):
    Name = models.CharField(max_length=100)
    Population = models.CharField(max_length=100)
    Language = models.IntegerField()
    Total_persons= models.IntegerField()

class Person(models.Model):
    Country = models.ForeignKey(Country, on_delete=models.CASCADE, null=True)
    name = models.CharField(max_length=100)
    contact = models.IntegerField()

Country我有美国、加拿大、墨西哥、西班牙、法国...... 在Person我有1000多人。

我怎样才能使Total_persons 在该国家/地区随着Persons 总数的增加而增加。

【问题讨论】:

    标签: python django python-3.x django-models


    【解决方案1】:

    您可以删除该字段并简单地获取属于Country 实例countryPersons 的数量,而不是将Total_persons 设为一个单独的字段:

    country.person_set.count()
    

    或者如果你喜欢更友好的名字,你可以给Person中的Country外键一个related_name

    class Person(models.Model):
        Country = models.ForeignKey(Country, related_name='persons', on_delete=models.CASCADE, null=True)
    

    这样你就可以得到相同的计数:

    country.persons.count()
    

    或者,如果您仍然希望将 Total_persons 设为单独的字段,则可以在创建 Person 实例时覆盖 Person.save() 方法以同步其国家/地区(当其 pkNone 时) ,并在Person 实例被删除时覆盖Person.delete() 方法以进行同步:

    class Person(models.Model):
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            if not self.pk:
                self.Country.Total_persons = self.Country.person_set.count()
                self.Country.save()
        def delete(self):
            country = self.Country
            super().delete()
            country.Total_persons = country.person_set.count()
            country.save()
    

    【讨论】:

      【解决方案2】:

      您的模型字段名称应为小写。 请参阅Coding Style-Model 了解更多信息。此外,您的人口和语言字段似乎没有正确的数据类型??

      实现所需的另一种方法是使用模型属性。

      class Country(models.Model):
          name = models.CharField(max_length=100)
          population = models.CharField(max_length=100)
          language = models.IntegerField()
      
          @property
          def total_people(self):
              return self.people.count()
      
      class Person(models.Model):
          Country = models.ForeignKey(Country, on_delete=models.CASCADE, null=True,
                                      related_name='people')
          name = models.CharField(max_length=100)
          contact = models.IntegerField()
      

      【讨论】:

      • 您应该使用.count() 而不是len(self.countries),否则将评估查询集的计数,其中只有数据库请求可以给出要求。
      • @Zulu 我已经更改了答案以反映这一点。如果您可以删除反对票会很好,因为我的回答是正确的。
      【解决方案3】:

      您有几种方法可以获取没有数据库字段的国家/地区的人数:

      annotations:

      qs = Country.objects.annotate(total_people=models.Count('person_set'))
      for country in qs:
          print(country.total_people)
      

      如果你真的想要一个数据库字段,你可以使用 post/pre 钩子。 有:

      • Post save

        @receiver(post_save, sender=Person)
        def increment_total_people(sender, instance, created, **kwargs):
            instance.Country.Total_persons += 1
            instance.Country.save()
        
      • Post delete

        @receiver(post_delete, sender=Person)
        def decrement_total_people(sender, instance, **kwargs):
            instance.Country.Total_persons -= 1
            instance.Country.save()
        

      但是当这个数字可能发生变化时,您必须针对所有用例进行设计。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-14
        • 1970-01-01
        • 1970-01-01
        • 2013-11-04
        • 2016-07-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多