Django与用户默认身份验证模型和其他模型的关系

时间:2020-08-06 19:27:35

标签: python django

我正在开发一个Web应用程序,用户可以在其中订阅系统内部可以看到的不同系列的文本。我想在UserSeriesText之间创建一个关系,因此我可以在VIEW中获取当前登录的用户,然后在仪表板模板处返回其所有订阅。 用户可以根据需要订阅任意数量的系列。

我正在使用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)时也出现错误,不知道为什么。

我真的很困惑,如果我需要双向关系,比如在models.ManyToMany模型和扩展SeriesText模型上创建User(我什至都​​不知道这是否真的是方法)。我什至不确定使用默认的auth用户模型建立关系的正确方法。

为了以后能够搜索所有订阅了该系列的用户,我认为models.ManyToMany也应使用SeriesText模型,这是否正确?

有人可以帮助我了解我是否使用了正确的关系(多对多),以及如何建立这种关系?预先感谢,我是Django的新手,在这里碰壁。

1 个答案:

答案 0 :(得分:1)

您只需要在SeriesText上添加一个m2m字段。从根本上讲,连接多对多字段的模型无关紧要(数据库看起来将是相同的,并且如果不相同,则数据访问将是相似的)。根据我的经验,最好不要弄乱Django用户模型:

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>]

如果未声明related_name,则必须使用默认值:

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

阅读效果不佳。