Как добавить все внешние отношения ключа в Джанго? - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть две модели:

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 в этой стране.

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Имена полей вашей модели должны быть строчными. См. Модель стиля кодирования для получения дополнительной информации. Кроме того, у вашего населения и языковых полей неправильный тип данных ??

Еще один способ добиться того, что вам нужно, - использовать свойства модели.

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()
0 голосов
/ 17 сентября 2018

У вас есть несколько способов узнать количество людей в странах без поля БД:

С аннотациями :

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

Иначе, если вы действительно хотитеесть поле БД, вы можете использовать post / pre hooks.Всего:

  • Сохранить сообщение

    @receiver(post_save, sender=Person)
    def increment_total_people(sender, instance, created, **kwargs):
        instance.Country.Total_persons += 1
        instance.Country.save()
    
  • Удалить сообщение

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

Но вам придется проектировать вещи для всех случаев использования, когда это число может измениться.

0 голосов
/ 17 сентября 2018

Вместо того чтобы делать Total_persons отдельным полем, вы можете удалить это поле и просто получить число Person s, принадлежащих Country экземпляру country с:

country.person_set.count()

Или, если вы предпочитаете более дружелюбное имя, вы можете указать Country внешний ключ в Person a 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.save() для синхронизации его страны при создании экземпляра Person (когда его pk равен None) и переопределите метод Person.delete() для синхронизации при удалении экземпляра Person:

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()
...