如何在save()中使用RelatedManager add()方法

时间:2013-06-05 19:17:42

标签: python django django-models django-related-manager

再次撞到墙上。 我正在尝试使用其他已知字段添加标签

# models.py
class MyModel(models.Model):
    ...
    tags = models.ManyToManyField(Tag, blank=True)
    field_m2m = models.ManyToManyField('M2mModel', blank=True)
    field_fk = models.ForeignKey('FkModel', blank=True, null=True)
    ...
    def save(self, *args, **kwargs):
        for inst in self.field_m2m.all():
            self.tags.add(Tag.objects.get(name=inst.name))
        self.tags.add(Tag.objects.get(name=self.field_fk.name))
        super(MyModel, self).save(*args, **kwargs)

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

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

我100%确定我的field_m2m和field_fk不是空的,并且重要性并不重要:有些实例对应于EXISTING标签。我还有其他功能很好地涵盖了这一部分。我也尝试过将字符串(Tag.objects.get(name="mystring"))硬编码为101%。

然而,没有通过管理面板分配标签。 我尝试在shell中执行这些步骤并在那里工作。

>>> m = MyModel.objects.get(name='something')
>>> t = Tag.objects.get(name='sometag')
>>> m.tags.add(t)
>>> m.tags.all()
[<Tag: sometag>]

如何使用save()方法使其工作?

在第一次创建模型实例之前,追溯正在抱怨:"<MyModel: Something>" needs to have a value for field "mymodel" before this many-to-many relationship can be used.

我想我应该在进行上述任务之前保存模型实例,对吧?我该如何一次完成所有工作?

2 个答案:

答案 0 :(得分:1)

在我保存任何关系之前,似乎必须将您的MyModel实例保存到数据库中。这是有道理的,因为对于关系,需要MyModel的id。因此,您可以更改save方法的顺序,如下所示:

def save(self, *args, **kwargs):
    # notice that super class save go first.
    super(MyModel, self).save(*args, **kwargs)
    # also this cicle doesn't make sense since self is a newly
    # created instance so it won't have anythin in field_m2m.all()
    for inst in self.field_m2m.all():
        self.tags.add(Tag.objects.get(name=inst.name))
    # this should work ok if get returns any tag.
    self.tags.add(Tag.objects.get(name=self.field_fk.name))

希望这有帮助!

答案 1 :(得分:0)

通过这个提示弄清楚:https://stackoverflow.com/a/6200451/1344854
模型save()方法保持默认。首先,我将标签绑定到我的FkModel和M2mModel实例。其余的工作是在ModelAdmin中完成的。

# models.py
class FkModel(models.Model):
    name = models.CharField(max_length=255, unique=True)
    tag = models.ForeignKey(Tag, blank=True, null=True, related_name='fk')
    ...

class M2mModel(models.Model):
    name = models.CharField(max_length=255, unique=True)
    tag = models.ForeignKey(Tag, blank=True, null=True, related_name='m2m')
    ...

# admin.py
class MyModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        form.save() # as I learned, without saving at this point, obj.field_m2m.all() will be empty
        tags = []
        if obj.field_m2m.all():
            tags += [m2m.tag for m2m in obj.field_m2m.all()]
        if obj.field_fk:
            tags += [obj.field_fk.tag]
        form.cleaned_data['tags'] = tags
        super(MyModelAdmin, self).save_model(request, obj, form, change)