如何将上下文变量从视图传递到Django模板中的自定义字段/小部件?

如何将上下文变量从视图传递到Django模板中的自定义字段/小部件?,django,django-forms,django-views,django-widget,Django,Django Forms,Django Views,Django Widget,我已经为一个表单定义了一个自定义字段和小部件,该表单由子类化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=MyC

我已经为一个表单定义了一个自定义字段和小部件,该表单由子类化
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)
from django.views.generic import UpdateView
from .forms import MyModelForm

class MyView(UpdateView):
    form_class = MyModelForm
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)
myapp/views.py

from .form_fields import MyCustomField
from .widgets import MyCustomWidget

class MyModelForm(forms.ModelForm):

    my_field = MyCustomField(queryset=MyModel.objects.all(), widget=MyCustomWidget)
from django.views.generic import UpdateView
from .forms import MyModelForm

class MyView(UpdateView):
    form_class = MyModelForm
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)
myapp/widgets.py

from .form_fields import MyCustomField
from .widgets import MyCustomWidget

class MyModelForm(forms.ModelForm):

    my_field = MyCustomField(queryset=MyModel.objects.all(), widget=MyCustomWidget)
from django.views.generic import UpdateView
from .forms import MyModelForm

class MyView(UpdateView):
    form_class = MyModelForm
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)

基本上,我希望能够将
自定义_数据
从我的视图(例如从会话存储或表单实例)传递到小部件

我明白了;我不完全确定这是否是最好的/推荐的方法,但它确实有效

首先,在视图中,使用自定义数据更新
get\u form\u 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
接下来,在表单的
\uuuu init\uuuu()
中,弹出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)
        )
最后,在您的自定义小部件类中,获取
\uuuu init\uuuu()
中的变量:


现在,
{{custom_data}}
模板变量在
myapp/widgets/my_custom_widget.HTML
的呈现HTML中可用

我正在研究一个类似的问题,我想我找到了一个更可靠、更通用的方法来解决这个问题

在您的解决方案中,您可以覆盖render(),以替换小部件中的其他上下文数据

然而,当我在Django源代码中探索这个概念时,我发现Django框架开发人员实际上以一种我认为更好的方式来处理这个问题

它们不重写render(),而是重写get_context(),如中的ChoiceWidget类所示


这种方法使您不必担心重新指定呈现代码和模板标识,这可能最好留给专业人士来解决。

您还可以覆盖小部件的get\u 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

但是如何将
上下文
请求
值传递给小部件的
获取上下文
?e、 例如,我有
context[obj]
以及如何在
get\u context(..)中访问它