我正在开发一个Web应用程序,用户可以在其中订阅系统内部可以看到的不同系列的文本。我想在User
和SeriesText
之间创建一个关系,因此我可以在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的新手,在这里碰壁。
答案 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()
阅读效果不佳。