Множественные отношения «многие ко многим» с related_name «+» приводят к неверному набору запросов - PullRequest
0 голосов
/ 03 ноября 2011

У меня есть модель Django, которая имеет два отношения «многие ко многим» с классом auth.User, например:

class Indicator(models.Model):
    friends = models.ManyToManyField(User, related_name="+")
    enemies = models.ManyToManyField(User, related_name="+")

related_name установлено в "+" , поэтому нет обратной связи , т.е. мне не нужны u.friends_set и u.enemies_set, если вы пользователь.

Добавление, удаление и очистка «друзей» и «врагов» работает нормально - если я проверяю непосредственно в базе данных (т.е. не через Django), я вижу изменения, отраженные так, как я и ожидал. Однако, если я получаю запрос, заданный через Django, я получаю список «врагов», использую ли я i.friends.all() или i.enemies.all() (при условии, что i является экземпляром индикатора).

Если я проверю ManyRelatedManager, я вижу, что атрибут through является правильным, что (если я правильно понимаю) позволяет корректно работать add / remove / clear:

>>> i.friends.through
<class 'project.app.models.Indicator_friends'>

Однако метод get_query_set в основном получает суперкласс (диспетчер пользователей) и вызывает для него фильтр с kwargs i.friends.core_filters, равным {'+__pk': 404L} (если идентификатор индикатора равен 404). Core_filters одинаковы как для «друзей», так и для «врагов», что объясняет, почему я неправильно получаю один и тот же набор запросов для обоих.

Я могу обойти это (без установки related_name): вместо i.friends.all() я могу использовать:

[friend.user for friend in i.friends.through.objects.filter(indicator__id=i.id)]

Однако это вряд ли изящно.

  1. Это ограничение системы Django "set related_name to '+'"? (Я не смог найти это нигде в документации), т. Е. Что вы можете использовать «+» только один раз для каждой отдельной пары «объект / объект»?
  2. Это ошибка в Django (то есть что-то для отчета )?
  3. Есть ли лучший способ обойти эту проблему?

(Django 1.3 - я не пробовал транк, но при чтении кода он выглядит так же, как в Python 2.7).

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

Глядя на django / db / models / fields / related.py, выясняется, что опция related_name = '+' действительно протестирована с последним фрагментом строки символов в ManyToOneRel.is_hidden (). Поэтому простое добавление «+» к любой строке должно помочь, позволяя вам иметь уникальные имена в одной модели и при этом игнорировать обратные отношения.

0 голосов
/ 03 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...