How do you save a relationship with an existing tag otherwise create the tag, in django views?

StackOverflow https://stackoverflow.com/questions/20105700

  •  03-08-2022
  •  | 
  •  

Question

In a many to many tagging system; how do you save a photo to the name of the tag already exists and still save the photo with the rest of the tags added through the form.

class Photo(models.Model):
    title = models.TextField(blank=False, null=True)
    path = models.FileField(blank=False, null=True, upload_to='photos/')


class Tag(models.Model):
    name = models.TextField(blank=False, null=True)
    photos = models.ManyToManyField(Photo)

Heres an example from the view that will raise an error with Tag.name unique=true. Granted there exists a photo foo with a tag bar.

photo = Photo(title='foo2')
photo.save()
bar = form.data['tag'] ** this is tag bar
bar = Tag(name=bar)
bar.save() **will raise error, name bar already exists so you cannot save it
bar.photos.add(instance)
Was it helpful?

Solution

I apologize for reviving this old question and being contrary, but I thought it might help for me to provide a full code snippet. I've mentioned get_or_create a couple times but either you're misunderstanding me or vice versa. This code should be the same as what you wrote, except it uses Django's get_or_create rather than reinventing it and needing to catch the IntegrityError:

instance = Photo(title=form.data['title'])
instance.save()
tag, created = Tag.objects.get_or_create(name=form.data['tags'])
tag.photos.add(instance)
return HttpResponse("Succesful Upload with Tags")

Hope this helps. :-)

OTHER TIPS

Unless I'm mistaken, the tag 'bar' will be connected to both foo and foo2. The way ManyToMany fields in Django work is by creating an extra table, where each entry has a foreign key to both of the things it connects to.

So, in your example, it would create a table photo_photo_tag, with a foreign key to a Photo and a foreign key to a Tag. Thus, the tag itself is only saved once in the tag table, but referenced by foreign key many times in photo_photo_tag.

For more information on how ManyToMany works, see the following:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
Django - enforcing ManyToManyField unique items

What I ended up doing was, adding setting the Tag model's name to unique. Then in the view doing a try on the save. If the name exists; it will still save the relation to that tag names id

        instance = Photo(title=form.data['title'])
        instance.save()
        tag = form.data['tags']
        tag = Tag(name=tag)
            try:
                tag.save() **if the tag is unique, it will save it then add relation
                tag.photos.add(instance)
            except IntegrityError, e:  ** if its not unique, grab the ID of that tag
                tag_id = Tag.objects.all().filter(name=tag)
                singletag = tag_id[0]
                singletag.photos.add(instance)  ** then add relation
        return HttpResponse("Succesful Upload with Tags")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top