python - Django 'ModelForm' 对象没有属性 'object'
问题描述
我有一个 ModelForm,我试图在禁用某些字段的情况下显示它。在这种情况下,process_id
。我的模型的重要部分如下所示:
模型.py
class Process(models.Model):
related_processes = models.ManyToManyField('self', blank=True, symmetrical=False)
process_id = models.CharField(max_length=20, primary_key=True)
normal_field = models.CharField(max_length=20)
# a lot of fields here...
所以基本上我有一个可以有零个或多个相关进程的进程。这就是我在 forms.py 上的内容:
表格.py
class ProcessForm(ModelForm):
class Meta:
model = Process
fields = '__all__'
class EditProcessForm(ProcessForm):
readonly_fields = ('process_id', )
def __init__(self, *args, **kwargs):
super(EditProcessForm, self).__init__(*args, **kwargs)
for field in (field for name, field in self.fields.items() if name in self.readonly_fields):
field.widget.attrs['disabled'] = 'true'
field.required = False
def clean(self):
for f in self.readonly_fields:
self.cleaned_data.pop(f, None)
return super(EditProcessForm, self).clean()
class NewVersionProcessForm(EditProcessForm):
readonly_fields = ('process_id', )
def __init__(self, *args, **kwargs):
super(NewVersionProcessForm, self).__init__(*args, **kwargs)
for field in (field for name, field in self.fields.items() if name in self.readonly_fields):
# field.widget.attrs['disabled'] = 'true'
# Remember this line ^
field.required = False
客户第一次填写表单时,我希望所有字段都是可编辑的,所以我使用 ProcessForm。但是当客户编辑流程时,我希望某些字段是只读的。我在 stackoverflow 上找到了这个不错的解决方案(不幸的是,我再也找不到它了),并且在我编辑流程时它工作得很好。EditProcessForm 和 NewVersionProcessForm 之间的区别在于它们的视图和__init__
.
视图.py
class ProcessFormView(FormView):
template_name = 'my_app/fill_form.html'
form_class = ProcessForm
def form_valid(self, form):
form.save()
return redirect('my_app:show_process_page', form.cleaned_data.get('process_id'))
class EditProcessView(UpdateView):
model = Process
form_class = EditProcessForm
template_name = 'my_app/edit_form.html'
pk_url_kwarg = 'process_id'
def post(self, request, process_id):
# This is a little hack I found here: https://stackoverflow.com/a/21262262/3773461
# to edit an immutable QueryDict.
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['process_id'] = process_id
request.POST._mutable = mutable
return super().post(request)
def form_valid(self, form):
form.save()
return redirect('my_app:show_process_page', self.kwargs['process_id'])
class NewVersionProcessView(EditProcessView):
template_name = 'my_app/new_version_form.html'
form_class = NewVersionProcessForm
def get(self, request, process_id):
try:
Process.objects.get(process_id=process_id)
return redirect('my_app:process_already_exists_page')
except Process.DoesNotExist:
self.object = Process(process_id=process_id)
last_id = self.object.get_last_version_id()
last_process = Process.objects.get(process_id=last_id)
last_process_dict = last_process.__dict__
related_processes = last_process.related_processes.all()[:]
exclude = ['_state', 'process_id']
for key, value in last_process_dict.items():
if key not in exclude:
self.object.__dict__[key] = value
# self.object.related_processes.add(*related_processes)
# Remember this line too ^
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.form_invalid(form)
def post(self, request, process_id):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return redirect('my_app:show_process_page', form.cleaned_data['process_id'])
第一个视图是一个带有 ProcessForm 的简单 FormView。第二个视图是一个UpdateView。在帖子中,我只是添加了表单上禁用的字段(因此不会正常传递)。在 form_valid 上,我只是将表单保存在其模型上(带有刚刚添加的字段)。
第三种观点是我目前的问题。请记住,我可以使用流程做 3 件事:创建新流程、编辑流程或创建现有流程的新版本。这第三种观点打算做第三种观点。在获取时,我检查我是否正在尝试创建一个已经存在的进程。如果没有,我创建进程并将基本进程上的所有有用数据复制到它,除了 ManyToMany 字段(第二个“记住这一行”),因为我无法找到不保存的方法首先是模型。在发布时,我正在检查表单是否有效,在 form_valid 上,我正在保存该过程。
什么有效
我可以很好地创建和编辑流程。编辑时的只读字段完美运行。模型按预期保存。此外,如果注释了第一个“记住这一行”,也就是说,如果所有字段都是可编辑的,我可以使用另一个现有流程作为基础 (NewVersionProcessView) 创建一个新流程。
什么不起作用
如果第一个“记住这一行”没有注释,也就是说,如果某些字段是只读的,我的视图在发布时会崩溃。最具体地说,在 form_invalid 上。我唯一能想到的是,不知何故,没有一个 Process 对象链接到我的 NewVersionProcessView。我不明白为什么,因为我总是self.object
在获取时分配一些东西。我无法在发布时从数据库中获取对象,因为它尚未保存。另外,我不明白为什么启用或禁用字段会影响self.object
. 请记住,唯一改变的是那条field.widget.attrs['disabled'] = 'true'
线。这是日志:
Request Method: POST
Request URL: http://127.0.0.1:8000/my_app/new_version/999-11/
Django Version: 2.0.7
Python Version: 3.4.4
Installed Applications:
['my_app.apps.MyAppConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
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.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "C:\Python34\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "C:\Python34\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "C:\Python34\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\base.py" in dispatch
89. return handler(request, *args, **kwargs)
File "C:\Users\***\Desktop\my_app\views.py" in post
124. return self.form_invalid(form)
File "C:\Python34\lib\site-packages\django\views\generic\edit.py" in form_invalid
61. return self.render_to_response(self.get_context_data(form=form))
File "C:\Python34\lib\site-packages\django\views\generic\edit.py" in get_context_data
67. return super().get_context_data(**kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\detail.py" in get_context_data
93. if self.object:
Exception Type: AttributeError at /my_app/new_version/999-11/
Exception Value: 'NewVersionProcessView' object has no attribute 'object'
如果需要,我可以提供 urls.py 和 htmls。任何帮助表示赞赏。
解决方案
推荐阅读
- javascript - Metaballs-js 语法错误“不能在模块外使用导入语句”
- python - Python:将函数返回值写入输出文件
- c# - 扩展方法不填充数组
- c - GCC 在有效的 stb_image.h 上产生错误
- c# - 如何从 launchsettings.json 获取当前应用程序 url
- django-rest-framework - 如何将 Simple JWT 用于自定义用户模型
- css - 如何在物化CSS中使背景图像适合全宽div
- javascript - Javascript chart.js 数据对象/数组
- r - 如何在 R 中计算此数据框的差异
- javascript - 用户输入的时间为零,即使在 javascript 中应该更多