django表单-将request.user传递到小部件呈现函数中
如何将request.user对象传递到我创建的自定义小部件的呈现函数中,或者从呈现函数中访问当前用户的最佳方式是什么?基于用户定制小部件并不是一件简单的事情。小部件是表示层中的一个实体,不应该知道请求上下文。您应该自定义表单,以获取多个窗口小部件中的一个或其更改的参数django表单-将request.user传递到小部件呈现函数中,django,django-forms,Django,Django Forms,如何将request.user对象传递到我创建的自定义小部件的呈现函数中,或者从呈现函数中访问当前用户的最佳方式是什么?基于用户定制小部件并不是一件简单的事情。小部件是表示层中的一个实体,不应该知道请求上下文。您应该自定义表单,以获取多个窗口小部件中的一个或其更改的参数 创建动态表单非常困难。我也遇到过这个问题。有时候,这是无法回避的。请注意,这是一个有点黑客,但它的工作。我觉得使用它有点恶心,但这是一个恼人的跨领域问题,Django人认为表单字段、小部件或过滤器访问请求上下文永远都不会好 如果
创建动态表单非常困难。我也遇到过这个问题。有时候,这是无法回避的。请注意,这是一个有点黑客,但它的工作。我觉得使用它有点恶心,但这是一个恼人的跨领域问题,Django人认为表单字段、小部件或过滤器访问请求上下文永远都不会好 如果这在
somelibrary/templatetags/widgethack.py
中:
from django import template
register = template.Library()
class _WidgetContextWrapper(object):
def __init__( self, widget=None, context=None ):
self.widget = widget
self.context = context
def __getattr__( self, attr ):
return getattr( self.widget, attr )
def render( self, name, value, attrs=None ):
try:
return self.widget.render( name, value, attrs=attrs, context=self.context )
except TypeError:
return self.widget.render( name, value, attrs=attrs )
def contextfield( context, field ):
return field.as_widget( widget=_WidgetContextWrapper( field.field.widget, context ) )
register.simple_tag(takes_context=True)(contextfield)
然后,您可以通过以下方式在模板中访问它:
{% load widgethack %}
{% contextfield some_field %}
然后,您只需确保所需字段具有覆盖render
的小部件,以接受附加的context=
参数:
from django import forms
from django.template.loader import render_to_string
from django.template.context import Context
class MyWidget( forms.widgets.TextInput ):
def render( self, name, value, attrs=None, context=None ):
attrs = attrs if attrs else {}
context = context if context else Context()
context.push()
context["do_what"]="you_want"
rendered = render_to_string("just_for_example.html",context)
context.pop()
return rendered
并使用该小部件:
from django import forms
from wherever import MyWidget
class MyModelForm( forms.ModelForm )
my_field = forms.CharField( widget=MyWidget )
...
唉,我在Django中发现的一个重大缺陷是,许多类确实需要成为类工厂,允许您覆盖内部类,如BoundField、ModelFormOptions和formset_factory等返回的类-P
我认为解决方案还不是一个黑客攻击(但接近),也没有那么大的麻烦
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['your_field'].widget.user = user
def __init__(self, *args, **kwargs):
self.user = None
super(YourWidget, self).__init__(*args, **kwargs)
显然,您需要向用户提供表单,在某些边缘情况下,这可能是一个问题,例如,您使用的是django动态视图,您不喜欢将其更改为更静态的方法。这个问题非常古老,但我刚刚遇到了同样的问题,我发现的解决方案似乎很好。下面的小部件只是一个带有一些说明的文本字段:
class TextInputWithInstructions(TextInput):
def __init__(self, *args, **kwargs):
self.instruction_text = kwargs['attrs'].pop('instruction_text')
super(TextInputWithInstructions, self).__init__(*args, **kwargs)
def render(self, name, value, attrs=None):
base_output = super(TextInputWithInstructions, self).render(name=name, value=value, attrs=attrs)
if self.instruction_text is not None:
base_output = '<p class="form-control-static">' + str(self.instruction_text) + '</p>' + base_output
return mark_safe(base_output)
你能给我们更多的背景吗?您可以使用自定义表单构造函数传入
请求
对象,然后可以使用django.forms.models.modelcoocefield
动态设置一个查询集,该查询集返回请求。用户
,并使用选择
小部件显示它,但是我猜您需要为演示文稿定制一些内容,可能是表单提供了一个不可编辑的字段,该字段的值是由表单提供的。
email_address = MultiEmailFieldString(label=_("Email address"), required=False,
widget=TextInputWithInstructions(
attrs={'instruction_text':
'Email notifications will be sent to addresses listed below.'}),
help_text=_("Separate multiple addresses with a comma."), )