10

我有一个 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 以在此处进行查找以及代码的确切工作方式。

一个代码示例或一个链接将不胜感激。

谢谢,皮特

4

5 回答 5

12

我刚刚完成了这项工作,因此会发布答案以防万一它对其他人有所帮助。

您可以像这样在 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, {})

您需要将模型转换为字典,以便将其设置为初始数据。

于 2012-12-11T16:50:59.823 回答
3

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 自动完成的。通过简单地返回一个空的初始值字典,您将拥有更简单、更高效的代码。

于 2015-01-06T20:45:23.057 回答
2

除了 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
于 2014-02-19T10:22:23.260 回答
2

我不得不稍微编辑一下,让它在 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

于 2018-02-19T02:10:12.047 回答
0

适用于 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)

我希望它可以帮助有同样问题的人。

于 2020-09-16T16:12:45.427 回答