简体   繁体   中英

Django adding item to many-to-many relationships

I'm new to django thus the question. I've the following Feed object and an User object which have a many-to-many relationship

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.

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:

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

Well, let's start from the beginning.

As you probably know, when you generate M2M rels with Django, you use the ManyToManyField . If you do not care about M2M table details, Django will manage it for you. If you want to specify the intermediary table you can use 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. 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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