![](/img/trans.png)
[英]Python Django: Use Form Wizard to Edit Model and check if request user is allowed to edit
[英]Django Form Wizard to Edit Model
我有一个 Django 表单向导,可以很好地创建我的模型之一的内容。 我想使用相同的向导来编辑现有内容的数据,但找不到如何执行此操作的好示例。
这是我的项目代码的简化版本:
表格.py
class ProjectEssentialsForm(forms.ModelForm):
class Meta:
model = Project
fields = [
'title',
'short_description',
'who_description',
'problem_description',
'solution_description'
]
class ProjectYourInfoForm(forms.ModelForm):
class Meta:
model = Project
fields = [
'gender',
'location',
'post_code',
'sector',
]
视图.py
TEMPLATES = {
'project_essentials': 'projects/essentials-form.html',
'project_your_info': 'projects/your-info-form.html',
}
class ProjectWizard(SessionWizardView):
instance = None
def get_form_instance(self, step):
"""
Provides us with an instance of the Project Model to save on completion
"""
if self.instance is None:
self.instance = Project()
return self.instance
def done(self, form_list, **kwargs):
"""
Save info to the DB
"""
project = self.instance
project.save()
def get_template_names(self):
"""
Custom templates for the different steps
"""
return [TEMPLATES[self.steps.current]]
网址.py
FORMS = [
('project_essentials', ProjectEssentialsForm),
('project_your_info', ProjectYourInfoForm),
]
urlpatterns = patterns('',
(r'^projects/add$', ProjectWizard.as_view(FORMS)),
)
我看到有这个功能https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/#django.contrib.formtools.wizard.views.WizardView.get_form_instance用于设置表单实例,但我不确定您将如何获取模型 ID 以在此处进行查找以及代码的确切工作方式。
一个代码示例或一个链接将不胜感激。
谢谢,皮特
我刚刚开始工作,所以会发布答案,以防它帮助其他人。
您可以像这样在 urls.py 中传递要编辑的项目的 ID:
(r'^projects/edit/(?P<project_id>[-\d]+)$', ProjectWizard.as_view(FORMS)),
然后,您可以使用以下代码查找项目
视图.py:
class ProjectWizard(SessionWizardView):
def get_form_initial(self, step):
if 'project_id' in self.kwargs and step == 'project_essentials':
project_id = self.kwargs['project_id']
project = Project.objects.get(id=project_id)
from django.forms.models import model_to_dict
project_dict = model_to_dict(project)
return project_dict
else:
return self.initial_dict.get(step, {})
您需要将模型转换为字典,以便将其设置为初始数据。
pxg 的回答是不够的。 正如 emin-buğra-saral 所指出的,它会创建模型的新实例,而不是对其进行编辑。 而 emin-buğra-saral 的回答本身是不够的。 要么不要覆盖get_form_initial方法,也不要设置 initial_dict 值或使用此答案中提供的实现。 这是你应该如何结合他们的答案:
在 urls.py 中:
(r'^projects/edit/(?P<project_id>[-\\d]+)$', ProjectWizard.as_view(FORMS)),
在views.py中:
class ProjectWizard(SessionWizardView):
def get_form_initial(self, step):
if 'project_id' in self.kwargs:
return {}
return self.initial_dict.get(step, {})
def get_form_instance(self, step):
if not self.instance:
if 'project_id' in self.kwargs:
project_id = self.kwargs['project_id']
self.instance = Project.objects.get(id=project_id)
else:
self.instance = Project()
return self.instance
虽然PXG的版本get_form_initial的实际上的工作(只要你还添加get_form_instance覆盖),没有必要来查找实例,提取其数据,并创建一个初始值字典。 所有这些都是在从initial_dict初始化实例之前由 ModelForm 自动完成的。 通过简单地返回一个空的初始值字典,您将拥有更简单、更高效的代码。
除了 pxg 的答案,get_form_instance 应该是这样的,否则您将不会编辑模型而是创建它的新实例:
def get_form_instance(self, step):
if not self.instance:
if 'initial_id' in self.kwargs:
initial_id = self.kwargs['initial_id']
self.instance = Project.objects.get(id=initial_id)
else:
self.instance = Project()
return self.instance
我不得不对其进行一些编辑以使其在 Django 1.11 中使用 django-formtools 2.1 工作。
class ProjectWizard(SessionWizardView):
def get_form_initial(self, step):
if 'project_id' in self.kwargs:
return {}
return self.initial_dict.get(step, {})
def get_form_instance(self, step):
if not self.instance_dict:
if 'project_id' in self.kwargs:
project_id = self.kwargs['project_id']
return Project.objects.get(id=project_id)
return None
get_form_instance
方法现在期望返回一个对象或 None 。
适用于 Django 3.1 和 django-formtools 2.2 的更新。 就我而言,我有两个模型(Colaborattor 和 User),通过 OneToOneField 连接。 我在步骤 0 中显示用户表单,在步骤 1 中显示合作者表单:
模型.py:
class Colaborattor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nome = models.CharField("Nome completo", max_length=128)
...
视图.py:
class UpdateColaborattorWizard(SessionWizardView):
form_list = [forms.UserRegisterForm, forms.ColaborattorForm]
template_name = "criar_colaborador.html"
def get_form_instance(self, step):
# step 0: user form
if 'colaborattor_pk' in self.kwargs and step == '0':
colaborattor_pk = self.kwargs['colaborattor_pk']
colaborattor = models.Colaborattor.objects.get(pk=colaborattor_pk)
user = colaborattor.user
return user
# step 1: colaborattor form
elif 'colaborattor_pk' in self.kwargs and step == '1':
colaborattor_pk = self.kwargs['colaborattor_pk']
colaborattor = models.Colaborattor.objects.get(pk=colaborattor_pk)
return colaborattor
# The default implementation
return self.instance_dict.get(step, None)
我希望它可以帮助有同样问题的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.