Как "заставить" разделять экземпляры модели между объектами в django при использовании prefetch_related()?

Мой вопрос таков:

  • Как "заставить" экземпляры модели быть общими?
  • В приведенном ниже примере вывода строка 3 и строка 5 имеют Person(2) с разными идентификаторами экземпляров объектов.
    • Это означает, что существует 2 экземпляра модели одного и того же объекта, на которые ссылаются из двух разных мест
    • .
    • Я бы хотел, чтобы они указывали на точно такой же экземпляр объекта.
    • Таким образом, будет только 1 экземпляр модели каждого объекта, на который будут ссылаться из нескольких разных мест
    • .
  • Кроме того, когда поле обновляется (например, p2.name = 'p_two'), я хотел бы, чтобы оно было "видно" либо при доступе к Person2 через любой из Group12 или Group23, без необходимости сохранять и получать данные снова. На данном этапе нет необходимости сохранять состояние модели в базе данных.

В документации сказано:

https://docs.djangoproject.com/en/4.1/ref/models/querysets/#:~:text=Одна%20разница%20к,и%20CPU%20времени.

Пример: models.py

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

    def __str__(self):
        return f'<{hex(id(self))} P({self.pk}) {self.name}>'


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

    def __str__(self):
        return f'<{hex(id(self))} G({self.pk}) {self.name}>'


class Membership(models.Model):
    person = models.ForeignKey(to=Person, on_delete=models.CASCADE)
    group = models.ForeignKey(to=Group, on_delete=models.CASCADE)
    member_nickname = models.CharField(max_length=128)

    def __str__(self):
        return f'<{hex(id(self))} M({self.pk}) of {self.person} in {self.group}>'

Пример tests.py

class MyTests(TestCase):
    def test_object_ids(self):
        p1 = Person.objects.create(name='person1')
        p2 = Person.objects.create(name='person2')
        p3 = Person.objects.create(name='person3')

        g12 = Group.objects.create(name='group1')
        g23 = Group.objects.create(name='group2')
        g31 = Group.objects.create(name='group3')

        Membership.objects.create(person=p1, group=g12, member_nickname='p1-in-g12')
        Membership.objects.create(person=p2, group=g12, member_nickname='p2-in-g12')
        Membership.objects.create(person=p2, group=g23, member_nickname='p2-in-g23')
        Membership.objects.create(person=p3, group=g23, member_nickname='p3-in-g23')
        Membership.objects.create(person=p3, group=g31, member_nickname='p3-in-g31')
        Membership.objects.create(person=p1, group=g31, member_nickname='p1-in-g31')

        gs = Group.objects.all().prefetch_related()
        for g in gs:
            print(g)
            for m in g.membership_set.all():
                print('\t', m)

Пример вывода:

Line 1: <0x2960a4b35b0 G(1) group12>
Line 2:      <0x2960a5cc310 M(1) of <0x2960a5cc730 P(1) person1> in <0x2960a4b35b0 G(1) group12>>
Line 3:      <0x2960a5ccb80 M(2) of <0x2960a5cc9a0 P(2) person2> in <0x2960a4b35b0 G(1) group12>>
Line 4: <0x2960a4af1c0 G(2) group23>
Line 5:      <0x2960a5cc8b0 M(3) of <0x2960a5ccc40 P(2) person2> in <0x2960a4af1c0 G(2) group23>>
Line 6:      <0x2960a5cc2e0 M(4) of <0x2960a5cc100 P(3) person3> in <0x2960a4af1c0 G(2) group23>>
Line 7: <0x2960a4af3a0 G(3) group31>
Line 8:      <0x2960a5cc4c0 M(5) of <0x2960a5cc730 P(3) person3> in <0x2960a4af3a0 G(3) group31>>
Line 9:      <0x2960a5c27f0 M(6) of <0x2960a5c25b0 P(1) person1> in <0x2960a4af3a0 G(3) group31>>
Вернуться на верх