My models are as follows:
我的模型如下:
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)
Relevant line from my PhotoUploadForm
我的PhotoUploadForm的相关行
tags = forms.CharField(max_length=250)
What I'm trying to do is take the tags field, split by comma it into a list, get_or_create them as PhotoTag objects, then add those to the Photo object in the current form. Probably in the form save method, right? Something like this (this is not working):
我要做的是取标签字段,用逗号分成一个列表,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
I think I have the principle correct, but the execution is not. I would appreciate guidance and learning the correct way to think about this!
我认为我的原则是正确的,但执行不是。我很感激指导和学习正确的思考方式!
Updated with error traceback:
更新了错误回溯:
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 个解决方案
#1
1
Edit:
编辑:
I misread you question sorry. You have a few problems here. The first is this line
我误解你的问题对不起。你在这里遇到一些问题。首先是这一行
[x.strip() for x in photo.tags.split(',')]
photo.tags
is actually a ManyToMany
here as
photo.tags实际上是这里的ManyToMany
photo = super(PhotoUploadForm, self).save(commit=False)
returns an unsaved Photo
object. You might actually want to use
返回未保存的Photo对象。你可能真的想要使用
tags = [x.strip() for x in self.cleaned_data['tags'].split(',')]
because self.clean_data
will contain the data in the form, and the Photo
object won't have the data atatched until after you have called save
on it.
因为self.clean_data将包含表单中的数据,并且Photo对象在您对其进行调用save之后才会获取数据。
You can't add ManyToMany
's until you have actually created the object in the database, because behind the scenes a ManyToMany
table looks roughly like this:
在实际在数据库中创建对象之前,不能添加ManyToMany,因为在幕后,ManyToMany表看起来大致如下:
class Photo_PhotoTag_M2M_table(models.Model):
photo = models.ForeignKey(Photo)
phototag = models.ForeignKey(PhotoTag)
In your PhotoUploadForm.save
function, the Photo
object actually gets created in the database when you do this line photo.save()
. So you need to add your manytomany's after you have created to form.
在PhotoUploadForm.save函数中,当您执行此行photo.save()时,实际上会在数据库中创建Photo对象。因此,您需要在创建表单后添加manytomany。
(https://docs.djangoproject.com/en/1.7/topics/db/examples/many_to_many/#many-to-many-relationships)
(https://docs.djangoproject.com/en/1.7/topics/db/examples/many_to_many/#many-to-many-relationships)
#2
0
I don't know how this works with forms but when overriding the save method for models, you can't access m2m fields directly, you must use the m2m_changed signal.
我不知道这对表单有什么用处,但是当覆盖模型的save方法时,你不能直接访问m2m字段,你必须使用m2m_changed信号。
I bet here the same is happening because the traceback is similar.
我打赌这里也是如此,因为追溯是类似的。
#1
1
Edit:
编辑:
I misread you question sorry. You have a few problems here. The first is this line
我误解你的问题对不起。你在这里遇到一些问题。首先是这一行
[x.strip() for x in photo.tags.split(',')]
photo.tags
is actually a ManyToMany
here as
photo.tags实际上是这里的ManyToMany
photo = super(PhotoUploadForm, self).save(commit=False)
returns an unsaved Photo
object. You might actually want to use
返回未保存的Photo对象。你可能真的想要使用
tags = [x.strip() for x in self.cleaned_data['tags'].split(',')]
because self.clean_data
will contain the data in the form, and the Photo
object won't have the data atatched until after you have called save
on it.
因为self.clean_data将包含表单中的数据,并且Photo对象在您对其进行调用save之后才会获取数据。
You can't add ManyToMany
's until you have actually created the object in the database, because behind the scenes a ManyToMany
table looks roughly like this:
在实际在数据库中创建对象之前,不能添加ManyToMany,因为在幕后,ManyToMany表看起来大致如下:
class Photo_PhotoTag_M2M_table(models.Model):
photo = models.ForeignKey(Photo)
phototag = models.ForeignKey(PhotoTag)
In your PhotoUploadForm.save
function, the Photo
object actually gets created in the database when you do this line photo.save()
. So you need to add your manytomany's after you have created to form.
在PhotoUploadForm.save函数中,当您执行此行photo.save()时,实际上会在数据库中创建Photo对象。因此,您需要在创建表单后添加manytomany。
(https://docs.djangoproject.com/en/1.7/topics/db/examples/many_to_many/#many-to-many-relationships)
(https://docs.djangoproject.com/en/1.7/topics/db/examples/many_to_many/#many-to-many-relationships)
#2
0
I don't know how this works with forms but when overriding the save method for models, you can't access m2m fields directly, you must use the m2m_changed signal.
我不知道这对表单有什么用处,但是当覆盖模型的save方法时,你不能直接访问m2m字段,你必须使用m2m_changed信号。
I bet here the same is happening because the traceback is similar.
我打赌这里也是如此,因为追溯是类似的。