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

时间:2012-12-11 15:25:18

标签: python django

我有一个Django表单向导,可以很好地创建我的某个模型的内容。我想使用相同的向导来编辑现有内容的数据,但无法找到如何执行此操作的良好示例。

以下是我的项目代码的简化版本:

forms.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',
        ]

views.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]]

urls.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来进行查找以及代码的确切方式会工作的。

最受欢迎的是代码示例或指向其中的链接。

谢谢, 皮特

5 个答案:

答案 0 :(得分:11)

我刚刚完成了这项工作,所以如果有人帮助别人,我会发布答案。

您可以在urls.py中传递您要修改的项目的ID,如下所示:

(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 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, {})

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

答案 1 :(得分: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自动完成的。只需返回一个空的初始值字典,您就可以获得更简单,更高效的代码。

答案 2 :(得分: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

答案 3 :(得分:1)

我不得不编辑这个以使它在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方法现在需要either an object or None to be returned

答案 4 :(得分:0)

与Django 3.1和django-formtools 2.2一起使用的更新。就我而言,我有两个模型(Colaborattor和User),它们通过OneToOneField连接。我在第0步中显示用户表单,在第1步中显示协作者表单。

models.py:

karate.configure('logModifier', new LM());

views.py:

class Colaborattor(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nome = models.CharField("Nome completo", max_length=128)
    ...

我希望它可以帮助遇到相同问题的人。