我有一个模型来保存用户帖子:
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)
因此,如果我在管理中保存一个新的 Post 对象,它会创建一个新的 Post 对象,还会在 tag_list 中创建标签对象。但是...它不会将tags_list中的标签添加到对象的多对多字段中(即post_object.tags)。
但是,如果我从 shell 创建一个新的 Post 对象,它会创建一个新的 Post 对象,在 tag_list 中创建标签对象,并将标签添加到 post.objects 标签字段中。
我在这里做错了什么?看来问题出在 django admin 中。
最佳答案
经过一番查找,终于解决了我的问题。因此,事实证明,如果您尝试对管理中的 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],以获取实例而不是创建的
。
信号.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)
关于django admin 不会将对象添加到 Manytomany 字段中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41478601/