如何在django视图中保存与现有标签的关系,否则创建标签?

时间:2013-11-20 19:57:53

标签: django models tagging

在多对多标记系统中;如何将照片保存到已存在的标签名称中,并保存照片,并通过表单添加其余标签。

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)

以下是视图中的示例,该示例将引发Tag.name unique = true的错误。 当然,存在带标签栏的照片foo。

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)

3 个答案:

答案 0 :(得分:1)

我为恢复这个老问题并为相反道歉,但我认为提供完整的代码片段对我有所帮助。我已经提到了get_or_create几次,但要么你误解了我,要么反之亦然。这段代码应该和你写的一样,除了它使用Django的get_or_create而不是重新发明它并需要捕获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")

希望这会有所帮助。 : - )

答案 1 :(得分:0)

除非我弄错了,标签'bar'连接到foo和foo2。 Django中的ManyToMany字段的工作方式是创建一个额外的表,其中每个条目都有一个外键来连接它。

因此,在您的示例中,它将创建一个表photo_photo_tag,其中包含Photo的外键和Tag的外键。因此,标记本身仅在tag表中保存一次,但在photo_photo_tag中多次使用外键引用。

有关ManyToMany如何工作的更多信息,请参阅以下内容:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
Django - enforcing ManyToManyField unique items

答案 2 :(得分:0)

我最终做的是,将Tag模型的名称设置为唯一。然后在视图中尝试保存。如果名称存在;它仍然会保存与标签名称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")