我有Form
ModelChoiceField
,form_class
用作FormView
。
必须使用绑定到request
对象的信息填充选择字段。
总结一下:
class MyFormView(FormView):
# I need to pass `request.user` and a value
# derived from `request.GET['pk']` to the form
form_class = MyForm
class MyForm(Form):
choices = ModelChoiceField(queryset=MyChoice.objects.none())
def __init__(self, user, number, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['choices'] = MyChoice.objects(number=number, owner=user)
在创建实例时,我需要做什么才能将数据传递给表单?
我尝试覆盖get_form
,但我不确定这是否是正确的方法:
def get_form(self, form_class):
user = self.request.user
number = SomeModel.objects.get(self.GET['pk']).number
return form_class(user, number, **self.get_form_kwargs())
答案 0 :(得分:2)
覆盖get_form
会有效,但更好的方法是覆盖get_form_kwargs
,这样您就不必重复get_form
方法中的代码。
class MyFormView(FormView):
form_class = MyForm
def get_form_kwargs(self):
kwargs = super(MyFormView, self).get_form_kwargs()
kwargs['user'] = self.request.user
kwargs['number'] = SomeModel.objects.get(self.GET['pk']).number
return kwargs
答案 1 :(得分:0)
我知道这是一个很长的答案; 相信我,最终结果是 很棒。
首先,我想传达的是,不需要具有辅助文件,例如 forms.py,tables.py和filters.py 正如大多数django教程所建议的。
Django随附了包括的电池;当我们运行 django-admin startapp 时,它将为我们创建所有必需的文件( admin,应用程序,模型,测试,视图)。
第二,我想说不需要可以创建单独的表单类。 我清楚地了解,必须使用Form类来自定义我们的表单;我只是说我们不需要明确定义它们。
Django强调 DRY(不要重复自己)原则。
如果您有机会浏览Django的源代码,您将发现重复使用了python内置的 Type function (Link to Official Documentation) 的特殊变体。
最后,在分享解决方案之前,我希望您观看以下视频,因为它可以帮助您理解此解决方案中使用的概念。
现在是 8行解决方案的时间(自从我进行了广泛的评论。以来,时间似乎更长了)
class MyFormView(FormView):
# I need to pass `request.user` and a value
# derived from `request.GET['pk']` to the form
# I am using the same class names (MyChoice, SomeModel) that were defined in previous responses
def get_form_class(self):
"""
Built-in Class Based View method to set the form class.
Takes current object (self) as argument
Returns a Class
"""
# Fetch the record object of interest
obj = SomeModel.objects.get(id=self.GET['pk'])
# Define the class attributes of the Form Class
cho = ModelChoiceField(queryset=MyChoice.objects.none())
# Define the class methods of the Form Class
def ini(s, *args, **kwargs): # s has been used instead of self to avoid ambiguity
# invoking the super class's init
super(type(s),s).__init__(*args,**kwargs)
# It is worth noting this function has access to:
# 1. self (Present view's instance)
# 2. obj (the variables defined within the parent function)
# 3. global variables and imports made in this file
# write your customizations below:
s.fields['choices'] = MyChoice.objects(number=obj.number, owner=self.request.user)
# Let's now return the Form Class variable using the "all powerful" type function
return type( \
type(self).__name__ + '_Form', # generate the Form Class Name \
(Form,), # Define the tuple of parent classes \
{'choices': cho, '__init__': ini} # value for the __dict__ attribute \
)
采用这种编码风格,我们所有的逻辑都停留在一个“ views.py ”位置。 同样的方法也可以扩展到表和过滤器(如果使用DjangoTables2)
希望您喜欢此解决方案。