处理现有记录时的 django 表单和 ModelMultipleChoiceField [英] django forms and ModelMultipleChoiceField when working with existing records
问题描述
我正在尝试做一些我认为很常见的事情,但我真的不确定如何解决这个问题.
我目前在做什么:目前我在我的表单上生成了一个复选框列表(使用CheckboxSelectMultiple"),它会自动勾选所有用户列表中成员"中的所有用户在 Django 中(由queryset=User.objects.all()"生成).
我真正想做的:我不想列出 Django 中的每个用户,我只想在成员"中显示用户列表.
我认为如何实现:我认为我可以通过将查询集修改为project.members.all()"之类的东西来做到这一点,其中 project = Project(项目).但是如何将此上下文传递给我的表单?
#models.py类项目(模型.模型):name = models.CharField(max_length=100)members = models.ManyToManyField(用户,相关名称=成员",空白=真,空=真)# 表单.py类 ProjectSettings(forms.Form):摘要 = forms.CharField(max_length=200)成员 = forms.ModelMultipleChoiceField(queryset=User.objects.all(), widget=forms.CheckboxSelectMultiple())#模板片段<form method="post" action="/projects/{{ project.slug }}/settings/save/">{% 用于表单 %} 中的字段<div class="form-row">{{ field.errors }}{{ field.label_tag }} {{ field }}{% if field.help_text %}<p class="help-text">{{ field.help_text }}</p>{% 万一 %}
{% 结束为 %}# 视图.pydef update_project(请求,project_slug):如果 request.method == 'POST':表单 = ProjectSettings(request.POST)if form.is_valid(): # 所有验证规则通过# 处理form.cleaned_data中的数据project.summary = form.cleaned_data['summary']project.members = form.cleaned_data['members']项目.save()return HttpResponseRedirect('/projects/' + project.slug + '/')别的:data_dict = {'summary':project.summary,'members':project.members.all()}表单 = ProjectSettings(initial=data_dict)return render_to_response('update_project.html', {'form': form}, context_instance=RequestContext(request))
我希望这是有道理的,我很抱歉,因为我真的认为这是我在这里遗漏的一些简单的东西 - 但我一直无法找到一个具体的例子来展示如何使用非模型表单来做到这一点.
提前致谢,
杰米
我猜你在项目模型中遗漏了一些东西.您的视图还调用了 project.members.all()
和 project.summary
而没有在 else 语句中获取项目.
假设你在projects模型中有一个summary字段,如果你想使用表单而不是模型表单,那么:
forms.py
class ProjectSettings(forms.Form):摘要 = forms.CharField(max_length=200)def __init__(self, qs=None, *args, **kwargs):super(ProjectSettings, self).__init__(*args, **kwargs)如果 qs:self.fields['members'] = forms.ModelMultipleChoiceField(queryset=qs, widget=forms.CheckboxSelectMultiple())
并且在您的 views.py 中,您会将 qs 传递给表单:
def update_project(request, project_slug):项目 = 无如果 project_slug:project = get_object_or_404(Project, name=project_slug) # 以某种方式获取你的项目对象qs = project.members.all()如果 request.method == 'POST':表单 = ProjectSettings(qs, request.POST)if form.is_valid(): # 所有验证规则通过# 处理form.cleaned_data中的数据project.summary = form.cleaned_data['summary']project.members = form.cleaned_data['members']项目.save()return HttpResponseRedirect('/projects/' + project.slug + '/')别的:表单 = 项目设置(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()元类:模型 = 项目字段 = ('摘要', '成员')
views.py:
def update_project(request, project_slug):项目 = 无如果 project_slug:project = get_object_or_404(Project, name=project_slug) # 以某种方式获取你的项目对象如果 request.method == 'POST':表单 = ProjectSettings(request.POST, instance=project)if form.is_valid(): # 所有验证规则通过# 处理form.cleaned_data中的数据项目.save()return HttpResponseRedirect('/projects/' + project.slug + '/')别的:表单 = 项目设置(实例 = 项目)return render_to_response('update_project.html', {'form': form}, context_instance=RequestContext(request))
I'm trying to do something which I would think is quite common, but I'm just really unsure how to tackle this.
What I currently do: Currently I produce a list of check boxes (using 'CheckboxSelectMultiple') on my form which auto ticks all the users who are in 'members' from the list of all Users in django (produced by "queryset=User.objects.all()").
What I want to actually do: I don't want to list every user in Django, I just want to show a list of Users in 'members'.
How I think it can be done: I think I can do this by modifying the queryset to be something like "project.members.all()" where project = Project (a specific instance of project). But how do I pass this context to my form?
# 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))
I hope this makes sense, and I do apologise as I really think this is something simple I'm missing here - but I haven't been able to find a specific example showing how to do this with non-model forms.
Thanks in advance,
Jamie
I'm guessing that you are leaving some stuff out of your Project model. Your view is also calling project.members.all()
and project.summary
with out getting a project in the else statement.
Assuming that you have a summary field in the projects model, if you want to use a form and not a model form, then:
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())
and in your views.py you would pass in the qs to the form:
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))
Using a ModelForm makes sense here if you do indeed have your summary field in your Project model.
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))
这篇关于处理现有记录时的 django 表单和 ModelMultipleChoiceField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!