Получить специфичные для сайта поля профиля пользователя из созданного пользователем объекта - PullRequest
0 голосов
/ 09 сентября 2018

Я использую структуру сайтов Django (Django 2.1), чтобы разделить приложение на несколько сайтов. Все мои модели, кроме модели User, зависят от конкретного сайта. Вот моя Post модель:

post.py

class Post(models.Model):
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        related_name='children',
        related_query_name='child',
        blank=True,
        null=True,
    )
    title = models.CharField(
        max_length=255,
        blank=True,
    )
    body_raw = models.TextField()
    body_html = models.TextField(blank=True)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    site = models.ForeignKey(Site, on_delete=models.CASCADE)
    on_site = CurrentSiteManager()

У меня нет проблем с разделением постов по сайту. Когда я хочу получить сообщения, я звоню:

posts = Post.on_site.filter(...)

У меня есть отдельная модель под названием UserProfile. Это профиль «многие к одному», где для каждой комбинации пользователь-сайт создается уникальный профиль (аналогично реализации профиля в SE). Профиль имеет атрибут reputation, к которому я хочу получить доступ при получении любого сообщения. Этот атрибут reputation должен отличаться для каждого сайта (например, как на SE у вас разные представители на каждом сайте, членом которого вы являетесь).

user_profile.py

class UserProfile(models.Model):
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    reputation = models.PositiveIntegerField(default=1)
    site = models.ForeignKey(Site, on_delete=models.CASCADE)
    on_site = CurrentSiteManager()

Как получить доступ к username пользователя (на модели User), а также к reputation пользователя (на модели UserProfile), когда я получаю Post s из запроса?

Я бы хотел сделать что-то вроде:

Post.on_site.filter(...)
    .select_related('user__userprofile')
    .filter_related(user__userprofile.site == get_current_site())

Как отфильтровать связанную модель «многие к одному»?

1 Ответ

0 голосов
/ 09 сентября 2018

Лучше сделать UserProfile -> User отношения, чтобы быть OnetoOne,
потому что Django не знает, какой из многих профилей показывать

(но вам также нужно определить related_name)

models.OneToOneField(get_user_model(), related_name='userprofile_rev')

Тогда вы сможете сделать это

qs = Post.on_site.filer().select_related('user', 'user__userprofile_rev')
for post in qs:
    print(post.user.username, post.user.userprofile_rev.reputation)

Если вы не хотите изменять структуру вашей БД, вы можете сделать это следующим образом
(но вам нужно указать, какой профиль вернуть)

qs = Post.on_site.filer().select_related('user').prefetch_related('user__userprofile_set')
for post in qs:
    print(post.user.username, post.user.userprofile_set[0].reputation)
...