Django - 在保存表单的同时创建m2m关系的对象

时间:2015-02-04 23:00:20

标签: django modelform

我的模型如下:

class Photo(models.Model):

  objects = PhotoManager()

  date = models.DateField()
  credit = models.CharField(max_length=60)
  sites = models.ManyToManyField(Site)
  tags = models.ManyToManyField('PhotoTag', related_name='photos')
  caption = models.CharField(max_length=255)
  timestamp = models.DateTimeField(auto_now=True)
  photo_src = models.ImageField()


class PhotoTag(models.Model):

  slug = models.CharField(max_length=255)

我的PhotoUploadForm的相关行

tags = forms.CharField(max_length=250)

我要做的是取标记字段,用逗号分隔成一个列表,get_or_create它们作为PhotoTag对象,然后将它们添加到当前表单中的Photo对象。可能在表单保存方法中,对吧?这样的事情(这不起作用):

def save(self, commit=True):

    photo = super(PhotoUploadForm, self).save(commit=False)

    tags = [x.strip() for x in photo.tags.split(',')]

    photo.tags = []

    for tag in tags:
      tag = PhotoTag.objects.get_or_create(slugify(tag))
      photo.tags.append(tag)

    if commit:
      photo.save()

    return photo

我认为我的原则是正确的,但执行不是。我很感激指导和学习正确的思考方式!

更新了错误追溯:

Traceback:
File "/vagrant/default_env/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/vagrant/default_env/lib/python3.4/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  22.                 return view_func(request, *args, **kwargs)
File "/vagrant/projects/bluehorse/bluehorse/apps/photos/views.py" in create_form
  46.       photo = form.save(commit=False)
File "/vagrant/projects/bluehorse/bluehorse/apps/photos/forms.py" in save
  31.     tags = [x.strip() for x in photo.tags.split(',')]
File "/vagrant/default_env/lib/python3.4/site-packages/django/db/models/fields/related.py" in __get__
  1175.             through=self.field.rel.through,
File "/vagrant/default_env/lib/python3.4/site-packages/django/db/models/fields/related.py" in __init__
  831.                                  (instance, source_field_name))

Exception Type: ValueError at /admin/photos/create
Exception Value: "<Photo: Photo object>" needs to have a value for field "photo" before this many-to-many relationship can be used.

2 个答案:

答案 0 :(得分:1)

编辑:

我误解了你的问题抱歉。你这里有一些问题。第一个是这一行

[x.strip() for x in photo.tags.split(',')]

photo.tags实际上是<{1}}

ManyToMany

返回未保存的photo = super(PhotoUploadForm, self).save(commit=False) 对象。您可能实际上想要使用

Photo

因为tags = [x.strip() for x in self.cleaned_data['tags'].split(',')] 将包含表单中的数据,并且self.clean_data对象在您调用Photo之后才会获取数据。

在实际在数据库中创建对象之前,不能添加save,因为在幕后,ManyToMany表看起来大致如下:

ManyToMany

class Photo_PhotoTag_M2M_table(models.Model): photo = models.ForeignKey(Photo) phototag = models.ForeignKey(PhotoTag) 函数中,当您执行此行PhotoUploadForm.save时,实际上会在数据库中创建Photo对象。因此,您需要在创建表单后添加许多内容。

https://docs.djangoproject.com/en/1.7/topics/db/examples/many_to_many/#many-to-many-relationships

答案 1 :(得分:0)

我不知道这对表单有何用处,但是当覆盖模型的保存方法时,您无法直接访问m2m字段,必须使用m2m_changed signal

我打赌这里也是如此,因为回溯是相似的。