Django - использование уникальных элементов ManyToManyField
Я пытаюсь сделать что-то простое:
members = models.ManyToManyField(User,blank=True,null=True,unique=True)
но уникальность не допускается. Когда вы смотрите на созданную таблицу, она делает внешние ключи, поэтому я предполагаю уникальность.
Я хочу иметь возможность связывать участников с этой моделью, представляющей группу. У группы нет членов, но я не хочу, чтобы один и тот же член мог присоединиться к группе дважды.
Моя мысль заключалась бы в том, что исключение будет выбрано, если я попытаюсь сделать это, но кажется, что исключение не выбрано.
def join(request,id):
user = request.user
mygroup = Group.objects.get(id=id)
mygroup.members.add(user)
mygroup.num_members+=1
mygroup.save()
num_members увеличивается, поскольку исключение не генерируется. Дублированные пользователи не отображаются в утилите администратора. Может ли add() терпеть неудачу? Должен ли я просто проверить, содержится ли пользователь уже перед добавлением?
Спасибо!
Ответы
Ответ 1
Во-первых, я бы не использовал num_members
. Вместо этого вы можете проверить, сколько членов есть с mygroup.members.count()
. Во-вторых, добавление элементов несколько раз не добавляет их более одного раза, так что вы в порядке.
A ManyToManyField
в Group
для member
, указывающий на User
, реализуется с отдельной таблицей (например, group_group_users
), которая имеет внешний ключ для Group
и User
. Пользователь может иметь несколько групп, а группа может иметь несколько пользователей, но не может быть двух строк в group_group_users
для одного и того же отношения (т.е. Уникальных вместе внешних ключей).
Использование:
>>> group = Group.objects.get(pk=1)
>>> user = User.objects.get(pk=1)
>>> group.members.add(user)
>>> # Worked fine as expected. Let check the results.
>>> group.members.all()
[<User: foousername>]
>>> group.members.add(user)
>>> # Worked fine again. Let check for duplicates.
>>> group.members.all()
[<User: foousername>]
>>> # Worked fine.
Ответ 2
Повторяющиеся пользователи не отображаются в утилите администратора.
Они не созданы.
Не удается ли добавить() с ошибкой?
Да.
Должен ли я просто проверить, содержит ли пользователь уже до добавления?
Да. Или вместо ручного подсчета пользователей вы можете просто подсчитать количество баз данных:
mygroup = Group.objects.filter(...).annotate(num_members=models.Count("members"))
Это устраняет необходимость в поле num_members
в реальной модели.
Кроме того, вы не должны использовать id
в качестве имени параметра для своей функции.