【问题标题】:Model Formset and regular ModelForm in same template?同一模板中的模型表单集和常规模型表单?
【发布时间】:2021-02-20 14:56:57
【问题描述】:

我有两个模型:

Project:

class Project(Model):
    
    name = CharField(max_length=50)
    members = ManyToManyField("accounts.User", through='ProjectUser')
    organization = ForeignKey(Organization, related_name="projects", on_delete=CASCADE)

    def __str__(self):
        return self.name

Task:

class Task(Model):
    task = CharField(max_length=100)
    project = ForeignKey(Project, on_delete=CASCADE)

    class Meta:
        db_table = 'task'

我有一个UpdateView 类:

class ProjectUpdateView(UpdateView):
    form_class = ProjectUpdateForm
    template_name = 'projects/project_edit.html'
    success_url = reverse_lazy('projects:list')

如何允许用户在编辑Project 实例的同一页面上添加任务(通过内联表单集)?

例如,用户可以在一个地方编辑Project name 和添加/删除Task 实例的一种合并表单

【问题讨论】:

    标签: django django-models django-forms inline-formset


    【解决方案1】:

    表单/表单集:

    首先,为您的任务模型创建一个表单和一个表单集

    class TaskForm(ModelForm):
        class Meta:
            model = Task
            fields = ['task']
    
        def __init__(self, *args, **kwargs):
            super(TaskForm, self).__init__(*args, **kwargs)
    
    
    
    class TaskBaseFormSet(BaseInlineFormSet):
        def __init__(self, *args, **kwargs):
            super(TaskBaseFormSet, self).__init__(*args, **kwargs)
    
    
    
    TaskFormset = inlineformset_factory(
        Project,  # parent_model
        Task,  # model
        form=TaskForm, 
        formset=TaskBaseFormSet
    )
    

    或者,如果您不需要 TaskForm 类,创建 TaskFormset 所需要做的就是这个

    TaskFormset = inlineformset_factory(Project, Task, fields=('task',))
    

    查看:

    我看到您正在为您的视图使用 UpdateView 类,因此您可以这样做以在您的 context_data 中获取一个 TaskFormset,因此现在您可以在您的“template_name”属性中声明的模板中使用 TaskFormset更新视图类

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
    
        if self.request.POST:
            context['task_formset'] = forms.TaskFormset(self.request.POST)
        else:
            context['task_formset'] = forms.TaskFormset()
    
    
        return context
    
    # In the form_valid method of your UpdateView class you can validate the data 
    # and assign the Project instance to all the tasks that were create by the formsets
    
    def form_valid(self, form):
    
         task_formset = context['task_formset']
    
         # you can validate formset data like this
         if not task_formset.is_valid():
            return self.form_invalid(form)
    
    
         project = form.save()
         # Here you assign the Project instance to the Tasks
         task_formset.instance = project
         task_formset.save()
    
         return super().form_valid(form)
    

    模板:

    现在您需要做的就是使用循环打印 management_form 和表单集中的每个表单,如下面的代码所示

    <form method="post">
    
        <!-- Your ProjectUpdateForm form here... -->
    
        {{ task_formset.management_form }}
        <table>
            {% for form in task_formset %}
            {{ form }}
            {% endfor %}
        </table>
    </form>
    

    希望这能有所帮助!有一些指向官方 Django 文档的链接可能对您有用:

    https://docs.djangoproject.com/en/3.1/topics/forms/formsets/#using-a-formset-in-views-and-templates

    https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/#inline-formsets

    https://docs.djangoproject.com/en/3.1/ref/forms/models/#inlineformset-factory

    【讨论】:

      猜你喜欢
      • 2012-08-13
      • 2010-10-28
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 2011-09-18
      • 2011-07-14
      相关资源
      最近更新 更多