自定义表添加多对多记录

自定义多对多表报错

今天使用多对多添加记录时,试了好多遍还是出现错误。
看代码
view.py

@login_required
def add_tag(request):
    if request.method == "POST":
        print(request.POST)
        tag_title = request.POST.get("tag_title")
        con_article = request.POST.getlist("con_article")
        blog = request.user.blog
        tag_obj = Tag.objects.create(blog=blog,title=tag_title)
        print(con_article)
        tag_obj.article2tag_set.set(*con_article)
        return redirect("/tag_manage/")
    else:
        article_list = Article.objects.all()
        return render(request,"add_tag.html",{"article_list":article_list})

model.py

class Tag(models.Model):
    """
    博客个人标签
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(verbose_name="标签名称",max_length=32)

    blog = models.ForeignKey(verbose_name="所属博客",to="blog",to_field="nid",on_delete=models.CASCADE)

    def __str__(self):
        return self.title

class Article(models.Model):
    """
    文章表
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=50,verbose_name="文章标题")
    desc = models.CharField(max_length=255,verbose_name="文章描述")
    create_time = models.DateTimeField(verbose_name="创建时间",auto_now_add=True)

    comment_count = models.IntegerField(default=0)
    up_count = models.IntegerField(default=0)
    down_count = models.IntegerField(default=0)

    user = models.ForeignKey(to="UserInfo",to_field="nid",verbose_name="作者",on_delete=models.CASCADE)
    category = models.ForeignKey(to="Category",to_field="nid",null=True,on_delete=None)
    tags = models.ManyToManyField(
        to="Tag",
        through='Article2Tag',
        through_fields=("article","tag"),
    )
    content = models.TextField()
    def __str__(self):
        return self.title

class Article2Tag(models.Model):
    """
    多表的第三张关联表
    """
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to="Article",to_field="nid",verbose_name="文章",on_delete=models.CASCADE)
    tag = models.ForeignKey(to="Tag",to_field="nid",verbose_name="标签",on_delete=models.CASCADE)

    class Meta:
        unique_together = [
            ('article','tag'),
        ]
    def __str__(self):
        v = self.article.title + "----" + self.tag.title
        return v

结果报错

TypeError at /add_tag/
'Article2Tag' instance expected, got '8'   

找到错误是这一行
tag_obj.article2tag_set.set(*con_article)

然后换
tag_obj.article_set.set(*con_article)

结果又报错

AttributeError at /add_tag/
Cannot set values on a ManyToManyField which specifies an intermediary model. Use blog.Article2Tag's Manager instead.

找到官方文档发现,多对多使用自定义第三张表时,操作和正常多对多操作不同

django官方文本

Unlike normal many-to-many fields, you can’t use add(), create(), or set() to create relationships:
Why? You can’t just create a relationship between a Person and a Group - you need to specify all the detail for the relationship required by the Membership model. The simple add, create and assignment calls don’t provide a way to specify this extra detail. As a result, they are disabled for many-to-many relationships that use an intermediate model. The only way to create this type of relationship is to create instances of the intermediate model.
The remove() method is disabled for similar reasons. For example, if the custom through table defined by the intermediate model does not enforce uniqueness on the (model1, model2) pair, a remove() call would not provide enough information as to which intermediate model instance should be deleted:   

翻译
不同于一般的多到很多领域,你不能使用add(),create()或者set()创建关系:
为什么?您不能只在a Person和a 之间创建关系Group - 您需要指定Membership模型所需关系的所有细节 。简单add,create并且分配调用不提供一种方式来指定这个额外的细节。因此,对于使用中间模型的多对多关系,它们被禁用。创建此类关系的唯一方法是创建中间模型的实例。

画重点,敲黑板

1.创建此类关系的唯一方法是创建中间模型的实例。
2.不能使用add(),create()或者set()创建关系:

简单说,需要我们自己手动往第三张表中添加两张表之间的关系

上修改后的代码

object_list = []
for i in range(len(con_article)):
    object_list.append(Article2Tag(tag=tag_obj,article_id=con_article[i]))
Article2Tag.objects.bulk_create(object_list)   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值