E
E
elky2011-11-23 18:50:53
Django
elky, 2011-11-23 18:50:53

Django - how to add value to ManyToManyField via admin?

Hello. Straight to the point. There are models:

class Tag(models.Model):<br>
    name = models.CharField(verbose_name=u'Tag', max_length=200, unique=True)<br><br>
class Entry(models.Model):<br>
    title = models.CharField(verbose_name=u'Entry title', max_length=200)<br>
    # всякие поля<br>
    tags_string = models.CharField(verbose_name=u'Tags', max_length=200, blank=True)<br>
    tags = models.ManyToManyField(Tag, null=True, blank=True)<br>

The tags_string field is filled in the admin panel, which looks like this at the output: “cat, dog, pig”
Then, I parse the string and add tags to the Tag table.
The task is to add a relationship between Entry and Tag. In other words, the post should have tags.
I'm trying to solve like this:
def save(self):<br>
    super(Entry, self).save()<br>
    if self.tags_string:<br>
        for tag in tags_string.split(","):<br>
            t = Tag.objects.create(name=tag.lstrip())<br>
            self.tags.add(t)<br>

The tags are added to the table, but the link table remains empty.
Exactly the same operation performed through the dzhang shell works with a bang. I guess the save() method is not so simple. Any ideas?
PS The most interesting thing is that links are not added even if you write like this:
def save(self):<br>
    super(Entry, self).save()<br>
    self.tags.add(3) # где 3 - id тэга.<br>

although through the same shell everything is ok.
Thank you in advance for your help.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
summerisgone, 2011-11-23
@elky

Your problem is in the admin. Automatic field for tags automatically removes tags.
If it is possible in your situation to remove this field painlessly, I advise you to do it.
Well, help:

class  Tag ( models. Model ) :
    name = models. CharField ( verbose_name=u 'Tag' , max_length= 200 , unique= True )
 
    def  __unicode__ ( self ) :
        return  self . name
 
class  Entry ( models. Model ) :
    title = models. CharField ( verbose_name=u 'Entry title' , max_length= 200 )
    tags_string = models. CharField (verbose_name=u 'Tags' , max_length= 200 , blank= True )
    # Note editable=False
    tags = models. ManyToManyField ( Tag, null= True , blank= True , editable= False )
 
    def  __init__ ( self ,  * args,  ** kwargs ) :
        super ( Entry,  self ) . __init__ ( * args,  ** kwargs )
        # Initialize ``tags_string`` with tag values
        if  self . pk :
            self . tags_string  =  ', ' . join ( self . tags . values_list ( 'name' , flat= True ) )
 
    def  save ( self ,  * args,  ** kwds ) :
        super ( Entry,  self ) . save ( * args,  ** kwds )
 
        names =  set ( [name. strip ( )  for  name  in  self . tags_string . split ( ',' ) ] )
        current =  set ( self . tags . values_list ( 'name' , flat= True ) )
        # Not only add but also remove tags
        exclude = current - names
 
        for  name  in  names:
            tag, created = Tag. objects . get_or_create ( name=name )
            self. tags . add ( tag )
        for  name  in  exclude:
            tag = Tag. objects . get ( name=name )
            self . tags . remove ( tag )
 

admin:
class  EntryAdmin ( admin. ModelAdmin ) :
    model = Entry
    list_display =  ( 'title' ,  'tag_list' )
 
    def  tag_list ( self , obj ) :
        return  ', ' . join ( obj. tags . values_list ( 'name' , flat= True ) )
 
admin. site . register ( Entry, EntryAdmin )

And don't you want to use django-taggit or django-tagging ?

E
elky, 2011-11-23
@elky

Thank you very much, buddy!

And do you want to use django-taggit or django-tagging?

Yes, I wanted mine.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question