我已经看到很多关于如何在不使用基于类的视图时解决这个问题的答案。是否有一些非常明显的事情我错过了用CBV做的事情?
基本上我想在我的表单中有一个MultipleChoiceField,其选择由视图中发生的事情决定。例如我使用URL中的PK来做一些后端请求,然后应该用它们来填充选项。
# forms.py
from django.forms import Form, MultipleChoiceField, CharField
class EmailForm(Form):
users = MultipleChoiceField(required=False)
subject = CharField(max_length=100)
message = CharField()
def __init__(self, users=None, *args, **kwargs):
super(EmailForm, self).__init__(*args, **kwargs)
if users:
self.fields['users'].choices = users
#urls.py
from django.conf.urls import url, patterns
from .views import EmailView
# url patterns
urlpatterns = patterns('',
url( r'^(?P<pk>\d+)$', EmailView.as_view(), name="maindex" ),
)
#views.py
from django.views.generic import FormView, TemplateView
from .forms import EmailForm
class EmailView(FormView):
template_name = 'myapp/email.html'
form_class = EmailForm
success_ulr = '/thanks/'
def form_valid(self, form):
# Do stuff here
return super(EmailView, self).form_valid(form)
基本上它归结为从视图中调用init函数的方式/位置。我怎么做?还是有另外一种我错过的方式?我想到了在视图中覆盖get_form_kwargs
,但无法做到这一点。
由于
答案 0 :(得分:14)
观点:
from django.views.generic import FormView
class EmailView(FormView):
# ...
def get_form_kwargs(self):
kwargs = super(EmailView, self).get_form_kwargs()
# get users, note: you can access request using: self.request
kwargs['users'] = users
return kwargs
表格:
from django import forms import Form
class EmailForm(Form):
users = MultipleChoiceField(required=False)
# ...
def __init__(self, *args, **kwargs):
self.users = kwargs.pop('users', None)
super(EmailForm, self).__init__(*args, **kwargs)
self.fields['users'].choices = self.users
答案 1 :(得分:3)
基本上,我在类似情况下所做的是以下内容(Python 3.5,Django 1.8):
string IndexName = "my_index";
this.client.CreateIndex(IndexName, c =>
c.AddMapping<CForm>
(m => m.Properties(ps => ps.Attachment
(a => a.Name(o => o.Document)
.TitleField(t => t.Name(x => x.Name)
.TermVector(TermVectorOption.WithPositionsOffsets))))));
// Create Mappings for the fields with specific properties.
// You can also make field1 a multi-field and make it both analyzed and not_analyzed
// to get the best of both worlds (i.e. text matching on the analyzed field + aggregation on the exact value
// of the not_analyzed raw sub-field).
// Field: Plan
var result = this.client.Map<CForm>(m => m
.Properties(props => props
.MultiField(s => s
.Name(p => p.Plan)
.Fields(pprops => pprops
.String(ps => ps.Name(p => p.Plan).Index(FieldIndexOption.NotAnalyzed))
.String(ps => ps.Name("original").Index(FieldIndexOption.Analyzed))
)
)
)
);
显然def get_form(self, *args, **kwargs):
form= super().get_form(*args, **kwargs)
form.fields['rank'].choices= <sequence of 2-tuples>
return form
是字段名称。这样我使用默认表单。
答案 2 :(得分:2)
好吧,FormMixin调用get_form
来获取看起来像
def get_form(self, form_class):
"""
Returns an instance of the form to be used in this view.
"""
return form_class(**self.get_form_kwargs())
因此,您可以覆盖get_form
以自行实例化您的表单
def get_form(self, form_class):
return EmailForm(files=self.request.FILES or None,
data=self.request.POST or None,
users=some_user_queryset)
或保持更加通用,并将get_form_kwargs
覆盖为类似
def get_form_kwargs(self):
form_kws = super(EmailView, self).get_form_kwargs()
form_kws["users"] = some_user_queryset
return form_kws
答案 3 :(得分:0)
一种方法是:
class EmailView(FormView):
# ...
def get(self, request, *args, **kwargs):
self.users = ...
return super(EmailView, self).get(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super(EmailView, self).get_form_kwargs()
kwargs['users'] = self.users
return kwargs
这允许您在视图中设置用户选项并将它们传递给表单。
答案 4 :(得分:0)
您可以覆盖 get_form 。
我需要根据登录用户更新ChoiceField的选择。
表格:
class InteractionCreateForm(forms.Form):
device = forms.ChoiceField(choices=[(None, '----------')])
...
查看:
class InteractionCreateView(FormView):
form_class = InteractionCreateForm
...
def get_form(self, form_class=None):
form_class = super().get_form(form_class=None)
form_class.fields['device'].choices = \
form_class.fields['device'].choices \
+ [(device.pk, device) for device in Device.objects.filter(owner=self.request.user.id)]
return form_class