我有一个模型可以保存用户帖子:
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。
答案 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)