Django набор запросов для пересечения полей отношений ManyToMany - PullRequest
1 голос
/ 25 января 2020

У меня сложная проблема, я пытаюсь выбрать модели, связанные друг с другом с помощью отношений ManyToMany, в зависимости от пересечения моделей, присутствующих в каждом из полей ManyToMany. Я пытался добиться этого с помощью F (), но безуспешно, я не думаю, что достаточно разбираюсь в DB / ORM, чтобы решить эту проблему.

Вот пример:

class Event(models.Model):
    want_private = models.ManyToManyField('User')

class User(AbstractUser):
    events = models.ManyToManyField(Event, related_name='users')

Сначала я хотел бы выбрать события из набора пользователей, например, начинающихся с "a":

users_a = User.objects.filter(username_startswith="a")

Таким образом, набор запросов должен быть:

Event.objects.filter(users=users_a)

Когда он получит сложным является то, что я хотел бы:

  • исключить события, когда пользователь одновременно находится в поле users события, в поле want_private событие и в наборе запросов users_a.
  • включают события, в которые пользователь одновременно входит в поле users события, не в поле want_private события и в наборе запросов users_a.

У кого-нибудь есть идея решить эту проблему?

Большое спасибо,

Камиль.

1 Ответ

0 голосов
/ 26 января 2020

Исходя из вашего комментария выше, кажется, что пользователь может быть связан с событием, и его ассоциация является либо публичной c, либо частной (я понимаю, что здесь может означать want_private). Если это так, то я предлагаю вам изменить структуру данных и сохранить эту информацию в виде через модель . Примерно так:

class Event(models.Model):
    # Remove want_private from here.

class User(AbstractUser):
    events = models.ManyToManyField(Event, related_name='users', through=UserEvent)

class UserEvent(models.Model):
    """ Through model between event and user. Store want_private here."""
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    want_private = models.BooleanField()  # This is now a boolean field

Как это работает, объясняется в документации, на которую я ссылался выше.

Теперь ваш запрос на событие становится намного проще:

Event.objects.filter(users__username__startswith='a', userevent__wants_private=False)

Это даст вам все события, в которых хотя бы один пользователь связан с этим событием, и их связь не является личной . Если в событии есть пользователи, попадающие в обе категории, тогда этот запрос будет включать это событие.

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

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