如何在视图和模板中结合 Django FormSet 和 QuerySet?
How to combine Django FormSet and QuerySet in view and template?
我有一个 Django 1.6 应用程序,它将包含一个显示客户列表的表单,每个名称旁边有一对 "Approve" 和 "Reject" 单选按钮,以指示我们是批准还是拒绝他们的付款方式。我希望在首次呈现表单时将每个单选按钮默认设置为 "Reject"。我还想在包含客户用户 ID 的每一行中包含一个隐藏的 "uid" 字段。当管理员单击每个用户名旁边的批准按钮 s/he 想要批准然后提交表单时,视图应该读取每个用户的每个隐藏 id 值,检查单选按钮,如果用户更新模型被批准。表单如下所示:
customer1 (hidden id) [ ] approve [x] reject
customer2 (hidden id) [ ] approve [x] reject
...
customerN (hidden id) [ ] approve [x] reject
我有三个问题不太明白如何解决:
- 如何将包含我的客户用户名和 ID 的查询集与将包含每个查询集对象的单选按钮对的表单集结合起来?我很确定我需要使用 FormSet 来保存单选按钮,我想我需要将表单集的 "initial" 值设置为查询集,但我无法将它们设置为 "connect" 以便表格看起来像我上面显示的那样。当我在浏览器中执行 "view source" 时,我没有看到我的帐户查询集对象。
- 如何通过 new_accounts 查询集将来自客户模型的用户列的客户 ID 连接到表单中的 uid 字段?
- 如何遍历提交的表单集并提取用户 ID 和单选按钮对象进行检查?
我真的很难全神贯注于这些任务。非常感谢您的帮助。
# views.py
def review_payment_methods(request, template):
if request.method == "POST":
payment_method_form = ReviewPaymentMethodForm(request.POST)
if payment_method_form.is_valid():
# How to iterate through form and pull out ids and radio button values??
# Update Account table here
return HttpResponseRedirect('/admin/')
else:
new_accounts = Account.objects.filter(method_approved=False).values()
PaymentMethodFormset = formset_factory(ReviewPaymentMethodForm, extra=new_accounts.count())
formset = PaymentMethodFormset(initial=new_accounts) # This doesn't seem to work
return render_to_response(template, locals(), context_instance=RequestContext(request))
# models.py
class Account(models.Model):
"""A user's account."""
user = models.OneToOneField(User, primary_key=True, unique=True)
method_approved = models.BooleanField(default=False) # This contains Approve/Reject
# forms.py
from django import forms
from django.utils.safestring import mark_safe
class ReviewPaymentMethodForm(forms.Form):
class HorizontalRadioRenderer(forms.RadioSelect.renderer):
def render(self):
return mark_safe(u'\n'.join([u'%s\n' % w for w in self]))
DECISION_CHOICES = (('1', 'Approve'), ('2', 'Reject'))
uid = forms.IntegerField(widget=forms.HiddenInput)
decision = forms.ChoiceField(
choices = DECISION_CHOICES,
widget = forms.RadioSelect(renderer=HorizontalRadioRenderer),
initial = '2', # 1 => Approve, 2 => Reject
)
# review_payment_methods.html
<div class="custom-content">
<h1>Review Payment Methods</h1>
<form action="." method="post">{% csrf_token %}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
<input type="submit" value="Submit" />
</form>
</div>
这实际上不是表单集的工作。您想要一个带有一组动态字段的单一表单;每个字段的名称是客户 UID,其值是接受或拒绝。为此,您可以在实例化表单时以编程方式创建字段:
class ReviewPaymentMethodForm(forms.Form):
def __init__(self, *args, **kwargs):
accounts = kwargs.pop('accounts')
super(ReviewPaymentMethodForm, self).__init__(*args, **kwargs)
for account in accounts:
self.fields[str(account.id)] = forms.ChoiceField(
label=account.user.username,
choices=DECISION_CHOICES,
widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
initial='2', # 1 => Approve, 2 => Reject
)
视图变为:
def review_payment_methods(request, template):
new_accounts = Account.objects.filter(method_approved=False)
if request.method == "POST":
payment_method_form = ReviewPaymentMethodForm(request.POST, accounts=new_accounts)
if payment_method_form.is_valid():
for acc_id, value in payment_method_form.cleaned_data.items():
approved = (value == '1')
Account.objects.filter(pk=acc_id).update(method_approved=approved)
return HttpResponseRedirect('/admin/')
else:
form = ReviewPaymentMethodForm(accounts=new_accounts)
return render(request, template, {'form': form})
我有一个 Django 1.6 应用程序,它将包含一个显示客户列表的表单,每个名称旁边有一对 "Approve" 和 "Reject" 单选按钮,以指示我们是批准还是拒绝他们的付款方式。我希望在首次呈现表单时将每个单选按钮默认设置为 "Reject"。我还想在包含客户用户 ID 的每一行中包含一个隐藏的 "uid" 字段。当管理员单击每个用户名旁边的批准按钮 s/he 想要批准然后提交表单时,视图应该读取每个用户的每个隐藏 id 值,检查单选按钮,如果用户更新模型被批准。表单如下所示:
customer1 (hidden id) [ ] approve [x] reject
customer2 (hidden id) [ ] approve [x] reject
...
customerN (hidden id) [ ] approve [x] reject
我有三个问题不太明白如何解决:
- 如何将包含我的客户用户名和 ID 的查询集与将包含每个查询集对象的单选按钮对的表单集结合起来?我很确定我需要使用 FormSet 来保存单选按钮,我想我需要将表单集的 "initial" 值设置为查询集,但我无法将它们设置为 "connect" 以便表格看起来像我上面显示的那样。当我在浏览器中执行 "view source" 时,我没有看到我的帐户查询集对象。
- 如何通过 new_accounts 查询集将来自客户模型的用户列的客户 ID 连接到表单中的 uid 字段?
- 如何遍历提交的表单集并提取用户 ID 和单选按钮对象进行检查?
我真的很难全神贯注于这些任务。非常感谢您的帮助。
# views.py
def review_payment_methods(request, template):
if request.method == "POST":
payment_method_form = ReviewPaymentMethodForm(request.POST)
if payment_method_form.is_valid():
# How to iterate through form and pull out ids and radio button values??
# Update Account table here
return HttpResponseRedirect('/admin/')
else:
new_accounts = Account.objects.filter(method_approved=False).values()
PaymentMethodFormset = formset_factory(ReviewPaymentMethodForm, extra=new_accounts.count())
formset = PaymentMethodFormset(initial=new_accounts) # This doesn't seem to work
return render_to_response(template, locals(), context_instance=RequestContext(request))
# models.py
class Account(models.Model):
"""A user's account."""
user = models.OneToOneField(User, primary_key=True, unique=True)
method_approved = models.BooleanField(default=False) # This contains Approve/Reject
# forms.py
from django import forms
from django.utils.safestring import mark_safe
class ReviewPaymentMethodForm(forms.Form):
class HorizontalRadioRenderer(forms.RadioSelect.renderer):
def render(self):
return mark_safe(u'\n'.join([u'%s\n' % w for w in self]))
DECISION_CHOICES = (('1', 'Approve'), ('2', 'Reject'))
uid = forms.IntegerField(widget=forms.HiddenInput)
decision = forms.ChoiceField(
choices = DECISION_CHOICES,
widget = forms.RadioSelect(renderer=HorizontalRadioRenderer),
initial = '2', # 1 => Approve, 2 => Reject
)
# review_payment_methods.html
<div class="custom-content">
<h1>Review Payment Methods</h1>
<form action="." method="post">{% csrf_token %}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
<input type="submit" value="Submit" />
</form>
</div>
这实际上不是表单集的工作。您想要一个带有一组动态字段的单一表单;每个字段的名称是客户 UID,其值是接受或拒绝。为此,您可以在实例化表单时以编程方式创建字段:
class ReviewPaymentMethodForm(forms.Form):
def __init__(self, *args, **kwargs):
accounts = kwargs.pop('accounts')
super(ReviewPaymentMethodForm, self).__init__(*args, **kwargs)
for account in accounts:
self.fields[str(account.id)] = forms.ChoiceField(
label=account.user.username,
choices=DECISION_CHOICES,
widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
initial='2', # 1 => Approve, 2 => Reject
)
视图变为:
def review_payment_methods(request, template):
new_accounts = Account.objects.filter(method_approved=False)
if request.method == "POST":
payment_method_form = ReviewPaymentMethodForm(request.POST, accounts=new_accounts)
if payment_method_form.is_valid():
for acc_id, value in payment_method_form.cleaned_data.items():
approved = (value == '1')
Account.objects.filter(pk=acc_id).update(method_approved=approved)
return HttpResponseRedirect('/admin/')
else:
form = ReviewPaymentMethodForm(accounts=new_accounts)
return render(request, template, {'form': form})