使用现有记录时,django表单和ModelMultipleChoiceField

时间:2011-03-20 10:06:01

标签: django django-forms

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

我目前正在做什么:目前我在我的表单上生成了一个复选框列表(使用“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))

我希望这是有道理的,并且我道歉,因为我真的认为这是一个简单的我在这里缺少 - 但我还没有找到一个具体的例子来展示如何用非模型形式做到这一点。

提前致谢,

杰米

1 个答案:

答案 0 :(得分:9)

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

假设您在项目模型中有一个摘要字段,如果您想使用表单而不是模型表单,那么:

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))