繁体   English   中英

用于编辑模型的 Django 表单向导

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM