简体   繁体   English

Django将项目添加到多对多关系

[英]Django adding item to many-to-many relationships

I'm new to django thus the question. 我是django的新手,因此是个问题。 I've the following Feed object and an User object which have a many-to-many relationship 我有以下Feed对象和User对象,它们之间具有多对多关系

class Feed(Base):
    headline = models.CharField(max_length=255)
    link = models.CharField(max_length=255)
    summary = models.TextField()
    reader = models.ManyToManyField(User, through='Bookmark')

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True, max_length=255)
    mobile = PhoneNumberField(null=True)
    username = models.CharField(null=True, unique=True, max_length=255)
    full_name = models.CharField(max_length=255, blank=True, null=True)

The two are related using the Bookmark object. 两者通过Bookmark对象关联。

class Bookmark(Base):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    feed = models.ForeignKey(Feed, on_delete=models.CASCADE, null=True)

My question is, 我的问题是

  1. How do I add a bookmark(or rather feed) to the user? 如何为用户添加书签(或供稿)?

  2. How do I fetch all the feeds the User has bookmarked? 如何获取用户已添加书签的所有供稿?

Any help appreciated. 任何帮助表示赞赏。

This is a good example for your problem 这是解决您的问题的好例子

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

For this models, if you want to add memberships, you do this: 对于此模型,如果要添加成员资格,请执行以下操作:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>

Unlike normal many-to-many fields, you can't use add(), create(), or set() to create relationships: 与普通的多对多字段不同,您不能使用add(),create()或set()创建关系:

>>> # The following statements will not work
>>> beatles.members.add(john)
>>> beatles.members.create(name="George Harrison")
>>> beatles.members.set([john, paul, ringo, george])

You can see this better in Django Docs 您可以在Django Docs中更好地看到这一点

Well, let's start from the beginning. 好吧,让我们从头开始。

As you probably know, when you generate M2M rels with Django, you use the ManyToManyField . 如您所知,当您使用Django生成M2M关系时,您将使用ManyToManyField If you do not care about M2M table details, Django will manage it for you. 如果您不关心M2M表的详细信息,Django将为您管理它。 If you want to specify the intermediary table you can use ManyToManyField.through . 如果要指定中间表,则可以使用ManyToManyField.through Exactly as you did. 确实和您一样。 I'm going to semplify your model for explanation purposes. 为了说明的目的,我将简化您的模型。 Something like this: 像这样:

class User(models.Model):
    username = models.CharField(null=True, unique=True, max_length=255)

class Feed(models.Model):
    headline = models.CharField(max_length=255)
    reader = models.ManyToManyField(User, through='Bookmark')

class Bookmark(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    feed = models.ForeignKey(Feed, on_delete=models.CASCADE, null=True)

Let's start Django interactive shell. 让我们开始Django交互式shell。 I assume you have an empty database. 我假设您有一个空数据库。

$ django manage.py shell

First of all import your models 首先导入模型

>>> from yourAppName.models import * 

Now, create some data: 现在,创建一些数据:

>>> from bat.models import *
>>> u1 = User(username = 'foo')
>>> u1.save()
>>> u2 = User(username = 'bar')
>>> u2.save()
>>> User.objects.all() # get Users u1 and u2
<QuerySet [<User: User object>, <User: User object>]>
>>> f1 = Feed(headline = 'How to use M2M in Django')
>>> f1.save()
>>> Feed.objects.all() # get Feed f1
<QuerySet [<Feed: Feed object>]>
  1. How do I add a bookmark (or rather feed) to the user? 如何为用户添加书签(或供稿)?

In this case, you cannot use Feed.reader.add(u1) , you have to use the Bookmark 's Manager since you specified that's your intermediary model. 在这种情况下,您不能使用Feed.reader.add(u1) ,因为您指定的是中间模型,所以必须使用Bookmark的Manager。

>>> b1 = Bookmark(user=u1, feed = f1) # add Feed f1 to User u1
>>> b1.save() # save into database

We can also add another bookmark: 我们还可以添加另一个书签:

>>> f2 = Feed(headline = 'Fetching data in Django like a pro!')
>>> f2.save()
>>> b2 = Bookmark(user=u1, feed = f2) # add Feed f2 to User u1
>>> b2.save() # save into database

You are done! 大功告成! Now, we can check if everything is fine. 现在,我们可以检查一切是否正常。

>>> brandNewBookMark = Bookmark.objects.all()[0] # get the first bookmark
>>> print(brandNewBookMark.user.username) # it's Foo!
foo
>>> print(brandNewBookMark.feed.headline) # Foo subscribed to f1!
u'How to use M2M in Django'
  1. How do I fetch all the feeds the User has bookmarked? 如何获取用户已添加书签的所有供稿?

You can simply leverage the Feed.reader field. 您可以简单地利用Feed.reader字段。 Eg, 例如,

>>> for f in Feed.objects.filter(reader = u1):
...     print(f.headline)
...    
How to use M2M in Django
Fetching data in Django like a pro!

That's it! 而已! Further info here . 进一步的信息在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM