Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
django表单-将request.user传递到小部件呈现函数中_Django_Django Forms - Fatal编程技术网

django表单-将request.user传递到小部件呈现函数中

django表单-将request.user传递到小部件呈现函数中,django,django-forms,Django,Django Forms,如何将request.user对象传递到我创建的自定义小部件的呈现函数中,或者从呈现函数中访问当前用户的最佳方式是什么?基于用户定制小部件并不是一件简单的事情。小部件是表示层中的一个实体,不应该知道请求上下文。您应该自定义表单,以获取多个窗口小部件中的一个或其更改的参数 创建动态表单非常困难。我也遇到过这个问题。有时候,这是无法回避的。请注意,这是一个有点黑客,但它的工作。我觉得使用它有点恶心,但这是一个恼人的跨领域问题,Django人认为表单字段、小部件或过滤器访问请求上下文永远都不会好 如果

如何将request.user对象传递到我创建的自定义小部件的呈现函数中,或者从呈现函数中访问当前用户的最佳方式是什么?基于用户定制小部件并不是一件简单的事情。小部件是表示层中的一个实体,不应该知道请求上下文。您应该自定义表单,以获取多个窗口小部件中的一个或其更改的参数


创建动态表单非常困难。

我也遇到过这个问题。有时候,这是无法回避的。请注意,这是一个有点黑客,但它的工作。我觉得使用它有点恶心,但这是一个恼人的跨领域问题,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

我认为解决方案还不是一个黑客攻击(但接近),也没有那么大的麻烦

  • 在窗体上重写init:

    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."), )