Django form - pass request.user to the widget render function

How do I pass the request.user object to the render function of the user widget that I created, or what is the best way to access the current user from within the render function

+3
source share
4 answers

Decision. I believe that this has not yet been hacked (but close), and it is not so difficult.

  • Override init in your forms:

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super(SomeForm, self).__init__(*args, **kwargs)
        self.fields['your_field'].widget.user = user
    
  • Redefine the widget:

    def __init__(self, *args, **kwargs):
        self.user = None
        super(YourWidget, self).__init__(*args, **kwargs)
    
  • Profit from your user widgets.

Obviously, you need to provide the user with a form, and this can be a problem in some cases, for example, you use dynamic django views, and you don't like changing them to a slightly more static approach.

+5
source

, . - . , .

.

+3

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

Alas, the one big drawback that I find in Django is that many classes really need to be classes that allow you to override inner classes such as BoundField, ModelFormOptions and the classes that formet_factory and others return .: -P </rant>

+1
source

The question is very old, but I had the same problem, and the solution I found seems to be good. The widget below is a text box with some instructions:

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)

Then the problem was passing the text_ instruction. which is solved as follows:

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

All Articles