首页 > 解决方案 > 如果数据库中不存在,则将输入标签添加到文章并创建新的标签记录

问题描述

我拥有多对多关系的数据模型TagArticle

class Tag(models.Model):
    owner = models.ForeignKey(User,on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    def __str__(self):
        return self.name
    class Meta:
        ordering = ("id",)

class Article(models.Model):
    tags = models.ManyToManyField(Tag, blank=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    ...

当接收到表单输入的标签时,我首先检查标签是否存在,以确定是否在数据库中创建一个新
的标签,然后将所有输入标签附加到一篇文章中。

#save the new article in database   
if article_form.is_valid():
    article = article_form.save(commit=False)
    article.owner = self.request.user
    article.save()
  1. 创建在记录中找不到的标签

    #compare tags
    input_tags = self.request.POST["tags"]
    input_tags = tags.split(",")
    query_tags = Tag.objects.all()
    #get name list of tab objects
    query_tags = [tag.name for tag in query_tags]
    #create new tabs in TabTable
    for tag in input_tags:
        if tag not in query_tags:
            Tag.objects.create(name=tag, owner=self.request.user)
    
  2. 检索输入标签对象

    tag_objs = []
    for input_tag in input_tags:
        try:
            qualified_tab = Tab.object.filter(name=input_tag)[0]
            tag_objs.append(qualified_tab)
    
  3. 将标签附加到文章

    article.tags.add(*tag_objs)
    

这是一项例行任务,但解决方案很麻烦。

如何优雅地完成这样的任务?

标签: pythondjango

解决方案


get_or_create(defaults=None, **kwargs)

一种使用给定 kwargs 查找对象的便捷方法(如果您的模型具有所有字段的默认值,则可能为空),如有必要,创建一个。

返回(object, created)的元组,其中 object 是检索或创建的对象, created 是指定是否创建新对象的布尔值。

if article_form.is_valid():
    article = article_form.save(commit=False)
    article.owner = self.request.user
    article.save()

   # tag list
   input_tags = self.request.POST["tags"]
   input_tags = tags.split(",")

   #create new tabs in TabTable
   for tag in input_tags:
       tag, created = Tag.objects.get_or_created(
                           name=tag, 
                           defaults={"owner":self.request.user})
       tag.article_set.add(article)
       #article.tags.add(tag) test

推荐阅读