Django 通用视图 form_valid 无法在指定中间模型的 ManyToManyField 上设置值
Django Generic View form_valid Cannot set values on a ManyToManyField which specifies an intermediary model
我在多对多关系中有三个表,一个产品 table,一个服务器 table 和一个中介 table link 这两个对象在一起。
每个服务器可以有多个产品,每个产品可以关联多个服务器。
这是我的模型
#/myapp/models.py
class Server(TimeStampedModel):
name = models.CharField(max_length=35)
description = models.CharField(max_length=200)
products = models.ManyToManyField('Product', through='ServerProduct',
related_name='products')
class ServerProduct(TimeStampedModel):
server = models.ForeignKey('Server', on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
class Product(TimeStampedModel):
name = models.CharField(max_length=200)
price = models.DecimalField(decimal_places=2, max_digits=11)
servers = models.ManyToManyField(
'Server', through='ServerProduct', related_name='servers')
在我的创建视图中,我指向一个允许用户创建服务器的表单,select它是相应的产品...
在 form_valid() 中,我正在尝试 link 每个产品到新服务器
#/myapp/views.py
class ServerCreateView(SuccessMessageMixin, CreateView):
model = Server
form_class = ServerForm
....
def form_valid(self, form):
server = form.save(False)
server.save()
for product in form.cleaned_data['products']:
ServerProduct.objects.create(server=server, product=product)
return super(ServerCreateView, self).form_valid(form)
我的表格如下所示..
class ServerForm(BlankToRequiredMixin):
class Meta:
model = Server
fields = '__all__'
widgets = {
'name': forms.TextInput(attrs={'autofocus': 'autofocus'}),
}
然而,当我提交表单 django returns 时出现以下错误:
Cannot set values on a ManyToManyField which specifies an intermediary
model. Use reports.ServerProduct's Manager instead.
代替ServerProduct.objects.create(server=server, product=product)
我也尝试了以下方法(在阅读文档here之后)但是这个returns同样的错误
prod = ServerProduct(server=server, product=product)
prod.save()
知道如何解决这个问题吗? (最好还是使用Generic create view)
编辑:完整追溯
Environment:
Request Method: POST
Request URL: http://localhost:8000/server-create/
Django Version: 1.9.7
Python Version: 3.4.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'auditlog',
'rest_framework',
'reports.apps.ReportsConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'auditlog.middleware.AuditlogMiddleware']
Traceback:
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in post
256. return super(BaseCreateView, self).post(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in post
222. return self.form_valid(form)
File "/home/jwe/piesup2/reports/views.py" in form_valid
182. return super(ServerCreateView, self).form_valid(form)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/contrib/messages/views.py" in form_valid
11. response = super(SuccessMessageMixin, self).form_valid(form)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in form_valid
201. self.object = form.save()
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/forms/models.py" in save
452. self._save_m2m()
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/forms/models.py" in _save_m2m
434. f.save_form_data(self.instance, cleaned_data[f.name])
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related.py" in save_form_data
1618. setattr(instance, self.attname, data)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related_descriptors.py" in __set__
481. manager.set(value)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related_descriptors.py" in set
882. (opts.app_label, opts.object_name)
Exception Type: AttributeError at /server-create/
Exception Value: Cannot set values on a ManyToManyField which specifies an intermediary model. Use reports.ServerProduct's Manager instead.
回溯显示错误发生在您在 form_valid
方法中调用 super()
时。
File "/home/jwe/piesup2/reports/views.py" in form_valid
182. return super(ServerCreateView, self).form_valid(form)
您已经在 form_valid
方法中保存了表单,因此无需调用 super()
。只需重定向到成功 url 即可。
def form_valid(self, form):
server = form.save(False)
server.save()
for product in form.cleaned_data['products']:
ServerProduct.objects.create(server=server, product=product)
return HttpResponseRedirect(self.get_success_url())
记得添加导入:
from django http import HttpResponseRedirect
我在多对多关系中有三个表,一个产品 table,一个服务器 table 和一个中介 table link 这两个对象在一起。
每个服务器可以有多个产品,每个产品可以关联多个服务器。
这是我的模型
#/myapp/models.py
class Server(TimeStampedModel):
name = models.CharField(max_length=35)
description = models.CharField(max_length=200)
products = models.ManyToManyField('Product', through='ServerProduct',
related_name='products')
class ServerProduct(TimeStampedModel):
server = models.ForeignKey('Server', on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
class Product(TimeStampedModel):
name = models.CharField(max_length=200)
price = models.DecimalField(decimal_places=2, max_digits=11)
servers = models.ManyToManyField(
'Server', through='ServerProduct', related_name='servers')
在我的创建视图中,我指向一个允许用户创建服务器的表单,select它是相应的产品...
在 form_valid() 中,我正在尝试 link 每个产品到新服务器
#/myapp/views.py
class ServerCreateView(SuccessMessageMixin, CreateView):
model = Server
form_class = ServerForm
....
def form_valid(self, form):
server = form.save(False)
server.save()
for product in form.cleaned_data['products']:
ServerProduct.objects.create(server=server, product=product)
return super(ServerCreateView, self).form_valid(form)
我的表格如下所示..
class ServerForm(BlankToRequiredMixin):
class Meta:
model = Server
fields = '__all__'
widgets = {
'name': forms.TextInput(attrs={'autofocus': 'autofocus'}),
}
然而,当我提交表单 django returns 时出现以下错误:
Cannot set values on a ManyToManyField which specifies an intermediary model. Use reports.ServerProduct's Manager instead.
代替ServerProduct.objects.create(server=server, product=product)
我也尝试了以下方法(在阅读文档here之后)但是这个returns同样的错误
prod = ServerProduct(server=server, product=product)
prod.save()
知道如何解决这个问题吗? (最好还是使用Generic create view)
编辑:完整追溯
Environment:
Request Method: POST
Request URL: http://localhost:8000/server-create/
Django Version: 1.9.7
Python Version: 3.4.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'auditlog',
'rest_framework',
'reports.apps.ReportsConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'auditlog.middleware.AuditlogMiddleware']
Traceback:
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in post
256. return super(BaseCreateView, self).post(request, *args, **kwargs)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in post
222. return self.form_valid(form)
File "/home/jwe/piesup2/reports/views.py" in form_valid
182. return super(ServerCreateView, self).form_valid(form)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/contrib/messages/views.py" in form_valid
11. response = super(SuccessMessageMixin, self).form_valid(form)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/views/generic/edit.py" in form_valid
201. self.object = form.save()
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/forms/models.py" in save
452. self._save_m2m()
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/forms/models.py" in _save_m2m
434. f.save_form_data(self.instance, cleaned_data[f.name])
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related.py" in save_form_data
1618. setattr(instance, self.attname, data)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related_descriptors.py" in __set__
481. manager.set(value)
File "/home/jwe/piesup2/venv/lib/python3.4/site-packages/django/db/models/fields/related_descriptors.py" in set
882. (opts.app_label, opts.object_name)
Exception Type: AttributeError at /server-create/
Exception Value: Cannot set values on a ManyToManyField which specifies an intermediary model. Use reports.ServerProduct's Manager instead.
回溯显示错误发生在您在 form_valid
方法中调用 super()
时。
File "/home/jwe/piesup2/reports/views.py" in form_valid
182. return super(ServerCreateView, self).form_valid(form)
您已经在 form_valid
方法中保存了表单,因此无需调用 super()
。只需重定向到成功 url 即可。
def form_valid(self, form):
server = form.save(False)
server.save()
for product in form.cleaned_data['products']:
ServerProduct.objects.create(server=server, product=product)
return HttpResponseRedirect(self.get_success_url())
记得添加导入:
from django http import HttpResponseRedirect