Как написать модель Django с отношениями ManyToMany с собой через модель

Я хочу иметь модель с отношением ManyToMany сама с собой, я не знаю, как это написать, но я попытаюсь написать код, чтобы проиллюстрировать, что я хочу сделать.

class Person(models.Model):
   name = models.CharField()
   occupation = models.CharField()

   friends = models.ManyToManyField('self', through = PersonFriends)

Моя модель, которую я хочу, чтобы друзья прошли

class PersonFriends(models.Model)
   ???
   comment = models.CharField()

В поле ManyToMany с сквозным отношением, если имя другой модели было, например, «Домашнее животное», я бы назвал свои поля в этом через класс person и pet и сделал их моделями. ForeignKey(Person) и Pet например

Как мне назвать мою fields в моей модели PersonFriends для двух полей человека теперь, когда они являются одной и той же моделью?


person Joelbitar    schedule 07.10.2010    source источник


Ответы (4)


Вы можете сделать что-то вроде этого:

class Person(models.Model):
    name = models.CharField(max_length = 255)
    occupation = models.CharField(max_length = 255)
    friends = models.ManyToManyField('self', through = 'PersonFriends', 
          symmetrical = False)
    #     ^^^^^^^^^^^
    # This has to be false when using `through` models. Or else your 
    # model will not validate.

class PersonFriends(models.Model):
    source = models.ForeignKey(Person, related_name = 'source')
    #                                  ^^^^^^^^^^^^
    # You need different `related_name` for each when you have 
    # multiple foreign keys to the same table. 

    target = models.ForeignKey(Person, related_name = 'target')
    comment = models.CharField(max_length = 255)
person Manoj Govindan    schedule 07.10.2010
comment
что означает определение ManyToManyField на той же модели ?? пожалуйста, объясните кому-нибудь - person ; 10.04.2018

Не предполагая, что дружба симметрична. Потому что Базз Лайтер может быть другом Вуди, но Вуди не дружит с Баззом Лайтером почти до конца фильма. Вы можете упростить обе модели и при этом иметь разумные имена для поиска. Вам, конечно, нужно убедиться, что вы определили двух PersonFriends, если это хорошая дружба.

class Person(models.Model):
   name = models.CharField()
   occupation = models.CharField()

class PersonFriends(models.Model):
    from_person = models.ForeignKey(Person, related_name='friends_with')
    to_person = models.ForeignKey(Person, related_name='friends')
    comment = models.CharField()
    class Meta:
        unique_together = ('from_person', 'to_person')

У этого есть дополнительный бонус комментария для каждого направления дружбы. то есть Тирион считает Сансу милой и умной, но потерянной девушкой. В то время как Санса может подумать, что Тирион некрасивый, но умный и добрый парень.

person Will S    schedule 18.12.2014

Все описано в официальной документации для ManyToManyField.through_fields (вы можете выполнить поиск по фразе "рекурсивные отношения", чтобы быстро найти то, что вам нужно):

для django 1.11 вы должны указать аргументы through и (!) through_fields:

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

    # note the additional arguments here
    friends = models.ManyToManyField(
        'self',

        # recursive relationships to self with intermediary
        # through model are always defined as non-symmetrical
        symmetrical=False,

        through='PersonFriend',

        # this argument is required to define a custom
        # through model for many to many relationship to self
        # position matters: 1 - source (from), 2 - target (to)
        through_fields=('person', 'friend'),        
    )


class PersonFriend(models.Model):
    # required relationship-defining foreign keys
    # (note that the order does not matter, it matters
    # in 'through_fields' argument in 'friends' field of the 'Person' model)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    friend = models.ForeignKey(Person, on_delete=models.CASCADE)

    # additional fields
    comment = models.CharField()
person Bob    schedule 01.07.2017

class PersonFriends(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_person')
    to_person = models.ForeignKey(Person, related_name='to_person')

это из структуры таблицы базы данных отношения ManyToMany к себе из моей структуры модели. Джанго определяет это так..

person FallenAngel    schedule 07.10.2010
comment
Габриэль Херли прав, вам нужно определить related_name, иначе django предупредит вас. Я получаю модель из структуры таблицы sql, поэтому я забыл добавить это, извините. - person FallenAngel; 07.10.2010