Django связь с моделью аутентификации пользователя по умолчанию и другой моделью - PullRequest
2 голосов
/ 06 августа 2020

Я разрабатываю веб-приложение, в котором пользователи могут подписаться на разные серии текстов, которые будут видны внутри системы. Я хочу создать связь между User и SeriesText, чтобы я мог захватить текущего зарегистрированного пользователя в ВИДЕ и просто вернуть все его подписки в шаблоне панели мониторинга. Пользователь сможет подписаться на любое количество серий.

Я использую модель User по умолчанию из django.contrib.auth.models, и я не уверен, как создать эту связь.

Я много читаю и думаю, что правильным использованием здесь будет Many-to-many (это правильно?), Поэтому я попробовал это, используя сводную таблицу / модель под названием Subscriptions:

from django.contrib.auth.models import User as BaseUserClass

class User(BaseUserClass):
    subscriptions = models.ManyToManyField(SeriesText, through="Subscription")


 class SeriesText(models.Model):
    series_name = models.CharField(max_length=255)
    series_text = models.CharField(max_length=255)
    subbed_users = models.ManyToManyField(User, through="Subscription")


class Subscription(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    series = models.ForeignKey(SeriesText, on_delete=models.CASCADE)

    def subscribe(self, user_id, series_id):
        self.user = user_id
        self.series = series_id
        self.save()

Но это, похоже, не сработало, у меня были ошибки даже при попытке использовать User.objects.get(pk=1), правда не знаю почему.

Я действительно сбит с толку, если мне нужно поставить отношения в обоих направлениях , например, created models.ManyToMany на модели SeriesText, и на расширенной модели User (что я даже не знаю, действительно ли это способ сделать это). Я даже не уверен, что это правильный способ установить отношения с использованием пользовательской модели аутентификации по умолчанию.

Чтобы иметь возможность позже также искать всех пользователей, подписанных на серию, я думаю, что models.ManyToMany также должен соответствовать модели SeriesText, это тоже правильно?

Может ли кто-нибудь помочь мне понять, использую ли я правильную связь (многие-ко-многим), и как установить эту связь? Заранее спасибо, я новичок в Django Я врезаюсь в стену.

1 Ответ

1 голос
/ 06 августа 2020

Вам нужно только добавить поле m2m на SeriesText. По сути, не имеет значения, к какой модели присоединено поле «многие ко многим» (база данных будет выглядеть так же, и доступ к данным будет аналогичным, если не идентичным). Исходя из моего опыта, лучше, если вам не придется возиться с моделью Django User:

class SeriesText(models.Model):
    series_name = models.CharField(max_length=255)
    series_text = models.CharField(max_length=255)
    subscribers = models.ManyToManyField(User, related_name='subscriptions')

    def __str__(self):
        return self.series_name

Чтобы увидеть, как это работает, сначала добавьте некоторые данные:

s1 = SeriesText.objects.create(series_name='name1', series_text='text1')
s2 = SeriesText.objects.create(series_name='name2', series_text='text2')

u1 = User.objects.create_user('user1')
u2 = User.objects.create_user(username='user2')
u3 = User.objects.create_user(username='user3')
u4 = User.objects.create_user(username='user4')
u5 = User.objects.create_user(username='user5')

s1.subscribers.add(u1, u2, u3)
s2.subscribers.add(u3, u4, u5)

Затем, чтобы получить всех подписчиков для SeriesText (я получаю объекты из базы данных здесь, чтобы показать, что это не артефакт двух последних строк выше - данные были изменены в базе данных):

>>> SeriesText.objects.get(series_name='name1').subscribers.all()
[<User: user1>, <User: user2>, <User: user3>]

>>> SeriesText.objects.get(series_name='name2').subscribers.all()
[<User: user3>, <User: user4>, <User: user5>]

для получения всех подписок для пользователя (мы заявили, что отношение от User к SeriesText должно иметь имя subscriptions в поле многие-ко-многим):

>>> User.objects.get(username='user1').subscriptions.all()
[<SeriesText: name1>]
>>> User.objects.get(username='user2').subscriptions.all()
[<SeriesText: name1>]
>>> User.objects.get(username='user3').subscriptions.all()
[<SeriesText: name1>, <SeriesText: name2>]
>>> User.objects.get(username='user4').subscriptions.all()
[<SeriesText: name2>]
>>> User.objects.get(username='user5').subscriptions.all()
[<SeriesText: name2>]

Если бы мы не ' t объявил related_name, нам пришлось бы использовать значение по умолчанию:

User.objects.get(username='user1').seriestext_set.all()

, которое также не читается.

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