我为子类UpdateView
提供服务的表单定义了自定义字段和小部件。所以,像这样:
myapp/forms.py
:
from .form_fields import MyCustomField
from .widgets import MyCustomWidget
class MyModelForm(forms.ModelForm):
my_field = MyCustomField(queryset=MyModel.objects.all(), widget=MyCustomWidget)
myapp/views.py
:
from django.views.generic import UpdateView
from .forms import MyModelForm
class MyView(UpdateView):
form_class = MyModelForm
myapp/widgets.py
:
from django.forms import Widget
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
class MyCustomWidget(Widget):
context_data = { 'custom_data': custom_data }
html_output = render_to_string('myapp/widgets/my_custom_widget.html', context_data)
return mark_safe(html_output)
基本上,我希望能够将custom_data
从我的视图(例如从会话存储或表单实例)传递到窗口小部件。
答案 0 :(得分:4)
我明白了;我不完全确定这是否是最佳/推荐的方式,但它确实有效。
首先,在视图中,使用自定义数据更新get_form_kwargs()
。例如,在我的情况下,我想使用附加到表单的实例中的额外数据。
# myapp/views.py
from .forms import MyModelForm
class MyView(UpdateView):
form_class = MyModelForm
def get_form_kwargs(self):
kwargs = super(MyView, self).get_form_kwargs()
form_instance = kwargs.get('instance')
extra_widget_data = form_instance.widget_data
kwargs.update({ 'extra_widget_data': extra_widget_data })
return kwargs
接下来,在您的表单__init__()
中,弹出kwarg并将其附加到该字段上的自定义窗口小部件:
# myapp/forms.py
from django import forms
from .widgets import MyCustomWidget
class MyModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
extra_widget_data = kwargs.pop('extra_widget_data')
super(MyModelForm, self).__init__(*args, **kwargs)
self.fields['my_custom_field'] = MyCustomField(
widget=MyCustomWidget(extra_widget_data=extra_widget_data)
)
最后,在您的自定义窗口小部件类中,抓取__init__()
中的变量:
# myapp/widgets.py
from django.forms import Widget
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
class MyCustomWidget(Widget):
def __init__(self, attrs=None, extra_widget_data=None):
super(MyCustomWidget, self).__init__()
self.extra_widget_data = extra_widget_data
def render(self, name, value, attrs=None):
context_data = { 'custom_data': self.extra_widget_data }
html_output = render_to_string('myapp/widgets/my_custom_widget.html', context_data)
return mark_safe(html_output)
现在,来自{{ custom_data }}
的呈现HTML中提供了myapp/widgets/my_custom_widget.html
模板变量。
答案 1 :(得分:1)
我正在研究类似的问题,我认为我找到了一种更可靠和更通用的方法来解决这个问题。
在您的解决方案中,您覆盖render()以将其他上下文数据替换为您的小部件。
然而,当我在Django源代码中探索这个概念时,我发现Django框架开发人员实际上以一种我认为更好的实践方式处理这个问题。
而不是覆盖render(),它们覆盖了get_context(),如https://docs.djangoproject.com/en/1.11/_modules/django/forms/widgets/的ChoiceWidget类中所示
这种方法使您不必担心重新指定渲染代码和模板识别,这可能最好留给专业人员。
答案 2 :(得分:0)
您还可以覆盖Widget的get_context方法:
# myapp/widgets.py
from django.forms import Widget
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
class MyCustomWidget(Widget):
template_name = 'myapp/widgets/my_custom_widget.html'
def __init__(self, attrs=None, extra_widget_data=None):
self.extra_widget_data = extra_widget_data
super(MyCustomWidget, self).__init__()
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context['custom_data'] = self.extra_widget_data
return context