django admin不会将对象添加到manytomany字段中

时间:2017-01-05 06:31:39

标签: django django-models django-admin

我有一个模型可以保存用户帖子:

class Tag(models.Model):
    name = models.CharField(max_length=255, unique=True)

class Post(models.Model):
    user = models.ForeignKey(User)
    body = models.TextField()
    tags = models.ManyToManyField(Tag, blank=True)
    pub_date = models.DateTimeField(default=timezone.now)
    activity = GenericRelation(Activity, related_query_name="posts")

现在每当我保存一个新的Post对象时,我想将Post对象的主体保存到Post对象的标签字段中。我这样做是使用信号:

@receiver(post_save, sender=Post)
def create(sender, instance, **kwargs):
    if kwargs.get('created', True):
        tag_list = [Tag.objects.create(name=word) for word in instance.body.split()]
        print "from signals!: instance body: %s" % instance.body
        instance.tags.add(*tag_list)

    if not kwargs.get('created', False):
        tag_list = [Tag.objects.create(name=word) for word in instance.body.split()]
        print "already signals!: instance body: %s" % instance.body
        instance.tags.add(*tag_list)

因此,如果我在admin中保存一个新的Post对象,它会创建一个新的Post对象,同时在tag_list中创建标记对象。但是......它没有将tags_list中的标记添加到对象的多对多字段中(即post_object.tags)。

但是,如果我从shell创建一个新的Post对象,它会创建一个新的Post对象,在tag_list中创建标记对象,并将标记添加到post.objects标记字段中。

我在这里做错了什么?似乎问题出在django admin。

1 个答案:

答案 0 :(得分:1)

经过大量搜索,我终于解决了我的问题。因此,事实证明,如果您尝试对管理员中的M2M字段执行某些操作,则更改将被clear()自动清除。

所以,我必须创建一个新的模型管理类:

class PostAdmin(admin.ModelAdmin):
    class Meta:
        model = Post

    def save_model(self, request, obj, form, change):
        print "from save_model"
        obj.save()

    def save_related(self, request, form, formsets, change):
        super(PostAdmin, self).save_related(request, form, formsets, change)
        obj = form.instance
        if obj.body:
            tag_list = [Tag.objects.get_or_create(name=word)[0] for word in obj.body.split() if word.startswith("#")]
            obj.tags.add(*tag_list)
            print("from save_related")
            obj.save()

admin.site.register(Post, PostAdmin)

另外,我改变了我在制作标签列表的方式,因为@Prakhar从create()指出了get_or_create()注意 get_or_create()期间的索引[0],以获取实例,而不是created

signals.py:

@receiver(post_save, sender=Post)
def create(sender, instance, **kwargs):
    if kwargs.get('created', True):
        tag_list = [Tag.objects.get_or_create(name=word)[0] for word in instance.body.split() if word.startswith("#")]
        print "from signals!: instance body: %s" % instance.body
        instance.tags.add(*tag_list)
    else:
        tag_list = [Tag.objects.get_or_create(name=word)[0] for word in instance.body.split() if word.startswith("#")]
        print "already signals!: instance body: %s" % instance.body
        instance.tags.add(*tag_list)