基于类视图的django初始化形式选择

时间:2013-11-19 21:43:33

标签: django forms class-based-views

我已经看到很多关于如何在不使用基于类的视图时解决这个问题的答案。是否有一些非常明显的事情我错过了用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,但无法做到这一点。

由于

5 个答案:

答案 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