【问题标题】:django forms and ModelMultipleChoiceField when working with existing records处理现有记录时的 django 表单和 ModelMultipleChoiceField
【发布时间】:2011-07-19 01:51:20
【问题描述】:

我正在尝试做一些我认为很常见的事情,但我真的不确定如何解决这个问题。

我目前的工作:目前我在我的表单上生成一个复选框列表(使用“CheckboxSelectMultiple”),它会自动勾选所有用户列表中“成员”中的所有用户在 django 中(由“queryset=User.objects.all()”产生)。

我真正想做的事情:我不想列出 Django 中的每个用户,我只想在“成员”中显示用户列表。

我认为如何做到这一点:我认为我可以通过将查询集修改为类似于“project.members.all()”的方式来做到这一点,其中 project = Project(项目)。但是如何将此上下文传递给我的表单?

# models.py
class Project(models.Model):
    name = models.CharField(max_length=100)
    members = models.ManyToManyField(User, related_name="members", blank=True, null=True)


# forms.py
class ProjectSettings(forms.Form):
    summary = forms.CharField(max_length=200)
    members = forms.ModelMultipleChoiceField(queryset=User.objects.all(), widget=forms.CheckboxSelectMultiple())


#template snippet
        <form method="post" action="/projects/{{ project.slug }}/settings/save/">
    {% for field in form %}
    <div class="form-row">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
        {% if field.help_text %}
        <p class="help-text">{{ field.help_text }}</p>
        {% endif %}
    </div>
    {% endfor %}


# view.py
def update_project(request, project_slug):
    if request.method == 'POST':
        form = ProjectSettings(request.POST)
        if form.is_valid(): # All validation rules pass
            # Process the data in form.cleaned_data
            project.summary = form.cleaned_data['summary']
            project.members = form.cleaned_data['members']
            project.save()
            return HttpResponseRedirect('/projects/' + project.slug + '/')
    else:
        data_dict = {'summary': project.summary, 'members': project.members.all()}
        form = ProjectSettings(initial=data_dict)

    return render_to_response('update_project.html', {'form': form}, context_instance=RequestContext(request))

我希望这是有道理的,并且我深表歉意,因为我真的认为这是我在这里遗漏的一些简单的东西 - 但我无法找到一个具体的示例来展示如何使用非模型表单执行此操作。

提前致谢,

杰米

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    我猜你在你的项目模型中留下了一些东西。您的视图也在调用project.members.all()project.summary,而没有在else 语句中获取项目。

    假设你在projects模型中有一个summary字段,如果你想使用一个表单而不是模型表单,那么:

    forms.py

    class ProjectSettings(forms.Form):
        summary = forms.CharField(max_length=200)
    
        def __init__(self, qs=None, *args, **kwargs):
            super(ProjectSettings, self).__init__(*args, **kwargs)
            if qs:
                self.fields['members'] = forms.ModelMultipleChoiceField(queryset=qs, widget=forms.CheckboxSelectMultiple())
    

    在您的views.py中,您可以将qs传递给表单:

    def update_project(request, project_slug):
        project = None
        if project_slug:
            project = get_object_or_404(Project, name=project_slug) # somehow get your project object  
    
        qs = project.members.all()
    
        if request.method == 'POST':
            form = ProjectSettings(qs, request.POST)
            if form.is_valid(): # All validation rules pass
                # Process the data in form.cleaned_data
                project.summary = form.cleaned_data['summary']
                project.members = form.cleaned_data['members']
                project.save()
                return HttpResponseRedirect('/projects/' + project.slug + '/')
        else:
            form = ProjectSettings(qs)
    
        return render_to_response('update_project.html', {'form': form}, context_instance=RequestContext(request))
    

    如果您的项目模型中确实有汇总字段,则在此处使用 ModelForm 是有意义的。

    forms.py:

    class ProjectSettings(forms.ModelForm):
        def __init__(self, qs=None, *args, **kwargs):
            super(ProjectSettings, self).__init__(*args, **kwargs)
            self.fields['members'].widget = forms.CheckboxSelectMultiple()
        class Meta:
            model = Project
            fields = ('summary', 'members')
    

    views.py:

    def update_project(request, project_slug):
        project = None
        if project_slug:
            project = get_object_or_404(Project, name=project_slug) # somehow get your project object  
    
        if request.method == 'POST':
            form = ProjectSettings(request.POST, instance=project)
            if form.is_valid(): # All validation rules pass
                # Process the data in form.cleaned_data
                project.save()
                return HttpResponseRedirect('/projects/' + project.slug + '/')
        else:
            form = ProjectSettings(instance=project)
    
        return render_to_response('update_project.html', {'form': form}, context_instance=RequestContext(request))
    

    【讨论】:

    • kriegar,非常感谢您的详细回复。是的,摘要是我的项目模型的一部分——对于令人尴尬的遗漏(将其替换为“名称”)我应该在发布前的十次重读中选择一次。
    猜你喜欢
    • 1970-01-01
    • 2017-10-09
    • 2020-03-03
    • 2013-03-31
    • 2013-11-13
    • 2010-09-20
    • 1970-01-01
    • 2015-07-04
    • 2019-09-29
    相关资源
    最近更新 更多