Django prefetch_related по неявному отношению

Допустим, я делаю приложение адресной книги.

class AddressBookEntry(models.Model):
    address_book = models.ForeignKey(AddressBook)
    name = models.CharField()
    email = models.EmailField()

class User(models.Model):
    name = models.CharField()
    email = models.EmailField()

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

    def entries(self):
        return AddressBookEntry.objects.filter(email=self.email)

Это отлично работает, но когда я получаю несколько пользователей, мне нужно выполнить запрос БД один раз для каждого пользователя. Я хотел бы сделать User.objects.all().prefetch_related('entries'), но это не работает, так как entries — это метод, а не ForeignKey.

So-

  • есть ли способ каким-то образом сказать django, что здесь есть связь, без явного наличия поля «многие ко многим» с его сквозной таблицей, поэтому я могу использовать select_related?
  • или есть ли способ выполнить JOIN между объектами, когда я извлекаю пользователей (я думаю, это будет перекрестное соединение, но это будет лучше, чем то, что у меня есть сейчас.)

person joerick    schedule 11.04.2014    source источник
comment
Это устаревшая база данных, которую вы не можете изменить? Если нет, почему бы вам просто не сделать поле email в AddressBookEntry отношением M2M к User?   -  person Selcuk    schedule 11.04.2014
comment
Электронная почта в AddressBookEntry вводится пользователем, они могут вводить адреса электронной почты людей, которые не являются пользователями приложения.   -  person joerick    schedule 11.04.2014
comment
Пожалуйста, добавьте определение модели AddressBookEntries в свой пост. Почему у вас есть и модель AddressBookEntries, и модель AddressBookEntry? Это кажется странным.   -  person garbanzio    schedule 20.12.2014
comment
@garbanzio извините, это опечатка. Я исправил пост.   -  person joerick    schedule 20.12.2014


Ответы (1)


Более "Django" способ сделать это - иметь явное поле отношения:

class AddressBookEntry(models.Model):
    address_book = models.ForeignKey(AddressBook)
    name = models.CharField()
    user = models.ForeignKey("User", related_name="entries")

class User(models.Model):
    name = models.CharField()
    email = models.EmailField()

User.objects.all().select_related('entries')
person Anentropic    schedule 20.12.2014