How to set value of a ManyToMany field in Django?

26,532

Solution 1

It looks like the problem here is that you're trying to add something to the M2M table before it's actually created in the database.

When you run post = Posts() you create an object in memory, but not in the database. So when you then try to add a new entry to the M2M table there is nothing to reference. (Remember that declaring an M2M field causes the creation of a new table with records that point to both ends of the relationship.)

The solution is to run post.save() before trying to add to the M2M table. (The Django admin is doing this for you behind the scenes.)

So try something like this:

post = Posts()

# now set up the post (title, name, etc.)

post.save() # adds a new entry to the Posts table

post.post_tagid.add(tag) # now that your post exists in the DB this should work

Solution 2

You should read official django docs on Many-to-many relationships.

In your case following code should help:

# Post object
post= Posts.objects.get(id=1)

# Two tag objects
tag1 = Tags.objects.get(id=1)
tag2 = Tags.objects.get(id=2)


# Add tag objects to Post object
post.post_tagid.add(tag1, tag2)
Share:
26,532
kidney win
Author by

kidney win

Python web developer:) Work with Django and pyramid, tornado, etc.

Updated on July 15, 2022

Comments

  • kidney win
    kidney win almost 2 years

    while learning Django to do web programming,I faced this problem. I searched Google and Django's official website biut could not find any answer. Please help me.

    System environment:

    1. Fedora 18
    2. Python 2.7
    3. Django 1.5.1
    4. Eclipse + PyDev

    Runtime: Django's development server

    I have a models includes ManyToMany field.When I set value by django's admin panel,everything goes well. Codes below are all of my models:

    class Posts(models.Model):
        post_authorid = models.IntegerField(verbose_name=u'Authorid')
        post_date = models.DateTimeField(auto_now_add=True,verbose_name=u'PostDate')
        post_date_modified = models.DateTimeField(auto_now=True,verbose_name=u'LastModifiedTime')
        post_content = models.TextField(verbose_name=u'Content')
        post_title = models.CharField(max_length=50,verbose_name=u'Title')
        post_name = models.CharField(max_length=50,blank=True,verbose_name=u'ShortName') 
        post_cover = models.CharField(max_length=200,verbose_name=u'CoverUrl')      
        post_introduction = models.CharField(max_length=500,blank=True,verbose_name=u'introduction')
        post_status = models.ForeignKey(Status,verbose_name=u'status')
        comment_status = models.BooleanField(verbose_name=u'show_comments')
        post_password = models.CharField(max_length=20,blank=True,verbose_name=u'passwd')
        post_tagid = models.ManyToManyField(Tags,verbose_name=u'tag')
        post_threadtypeid = models.ForeignKey(ThreadTypes,verbose_name=u'ThreadType')
        post_comment_conut = models.IntegerField(verbose_name=u'CommentsCount')
        post_comments = models.ManyToManyField(Comments,blank=True,verbose_name=u'Comment')
        def __unicode__(self):
            return u"%s %s %s" % (self.id,self.post_title,self.post_date)
        class Meta:
            ordering = ['post_date']
    class Tags(models.Model):
        tagname = models.CharField(max_length=20,verbose_name=u'标签名称')
        def __unicode__(self):
            return u"%s %s" % (self.id,self.tagname)
        class Meta:
            ordering = ['id']
    

    In my python shell,i input:

    post = Posts()
    
    post.post_tagid = Tags.objects.get(id='1')
    

    then django rasise a http 500 error:

    object needs to have a value for field "posts" before this many-to-many relationship can be used.

    But,when i use :

    post= Posts.objects.get(id='1')
    

    Note- I have input the Posts object by Django admin

    Then,when i use

    post.post_tagid = Tags.objects.get(id='1')
    

    everything goes well.

    Q:How can i add a ManyToMany field without this error raising?