machine - regresion lineal multiple en python
¿Cómo accedo al objeto de solicitud o cualquier otra variable en el método clean() de un formulario? (10)
Estoy intentando solicitar. Usuario para el método de limpieza de un formulario, pero ¿cómo puedo acceder al objeto de solicitud? ¿Puedo modificar el método de limpieza para permitir la entrada de variables?
El enfoque habitual es almacenar el objeto de solicitud en una referencia local de subprocesos utilizando un middleware. Luego puede acceder a esto desde cualquier lugar de su aplicación, incluido el método Form.clean ().
Cambiar la firma del método Form.clean () significa que tiene su propia versión modificada de Django, que puede no ser la que usted desea.
Gracias a la cuenta de middleware se ve algo como esto:
import threading
_thread_locals = threading.local()
def get_current_request():
return getattr(_thread_locals, ''request'', None)
class ThreadLocals(object):
"""
Middleware that gets various objects from the
request object and saves them in thread local storage.
"""
def process_request(self, request):
_thread_locals.request = request
Registre este middleware como se describe en los documentos de Django
La respuesta de Ber - almacenarla en threadlocals - es una muy mala idea. No hay absolutamente ninguna razón para hacerlo de esta manera.
Una forma mucho mejor es anular el método __init__
del __init__
para tomar un argumento de palabra clave adicional, request
. Esto almacena la solicitud en el formulario , donde se requiere, y desde donde puede acceder a ella en su método de limpieza.
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop(''request'', None)
super(MyForm, self).__init__(*args, **kwargs)
def clean(self):
... access the request object via self.request ...
y en su opinión:
myform = MyForm(request.POST, request=request)
La respuesta de Daniel Roseman sigue siendo la mejor. Sin embargo, usaría el primer argumento posicional para la solicitud en lugar del argumento de la palabra clave por algunas razones:
- No corre el riesgo de anular un kwarg con el mismo nombre
- La solicitud es opcional, lo cual no es correcto. El atributo de solicitud nunca debe ser Ninguno en este contexto.
- Puede pasar limpiamente los argumentos y kwargs a la clase principal sin tener que modificarlos.
Por último, usaría un nombre más único para evitar anular una variable existente. Por lo tanto, Mi respuesta modificada se ve así:
class MyForm(forms.Form):
def __init__(self, request, *args, **kwargs):
self._my_request = request
super(MyForm, self).__init__(*args, **kwargs)
def clean(self):
... access the request object via self._my_request ...
Me encontré con este problema en particular al personalizar el administrador. Quería que se validara un cierto campo en función de las credenciales del administrador en particular.
Como no quería modificar la vista para pasar la solicitud como un argumento al formulario, lo siguiente es lo que hice:
class MyCustomForm(forms.ModelForm):
class Meta:
model = MyModel
def clean(self):
# make use of self.request here
class MyModelAdmin(admin.ModelAdmin):
form = MyCustomForm
def get_form(self, request, obj=None, **kwargs):
ModelForm = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
def form_wrapper(*args, **kwargs):
a = ModelForm(*args, **kwargs)
a.request = request
return a
return form_wrapper
No siempre se puede usar este método (y es probable que sea una mala práctica), pero si solo se usa el formulario en una vista, se puede ubicar dentro del mismo método de visualización.
def my_view(request):
class ResetForm(forms.Form):
password = forms.CharField(required=True, widget=forms.PasswordInput())
def clean_password(self):
data = self.cleaned_data[''password'']
if not request.user.check_password(data):
raise forms.ValidationError("The password entered does not match your account password.")
return data
if request.method == ''POST'':
form = ResetForm(request.POST, request.FILES)
if form.is_valid():
return HttpResponseRedirect("/")
else:
form = ResetForm()
return render_to_response(request, "reset.html")
Para administrador de Django, en Django 1.8
class MyModelAdmin(admin.ModelAdmin):
...
form = RedirectForm
def get_form(self, request, obj=None, **kwargs):
form = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
form.request = request
return form
Por lo que vale, si está utilizando Vistas basadas en clases , en lugar de vistas basadas en funciones, anule get_form_kwargs
en su vista de edición. Código de ejemplo para un CreateView personalizado:
from braces.views import LoginRequiredMixin
class MyModelCreateView(LoginRequiredMixin, CreateView):
template_name = ''example/create.html''
model = MyModel
form_class = MyModelForm
success_message = "%(my_object)s added to your site."
def get_form_kwargs(self):
kw = super(MyModelCreateView, self).get_form_kwargs()
kw[''request''] = self.request # the trick!
return kw
def form_valid(self):
# do something
El código de vista anterior hará que la request
esté disponible como uno de los argumentos de palabras clave para la función del constructor __init__
del __init__
. Por lo tanto, en su ModelForm
hacer:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
# important to "pop" added kwarg before call to parent''s constructor
self.request = kwargs.pop(''request'')
super(MyModelForm, self).__init__(*args, **kwargs)
Tengo otra respuesta a esta pregunta según su requisito de que desea acceder al usuario en el método de limpieza del formulario. Puedes probar esto. View.py
person=User.objects.get(id=person_id)
form=MyForm(request.POST,instance=person)
forms.py
def __init__(self,*arg,**kwargs):
self.instance=kwargs.get(''instance'',None)
if kwargs[''instance''] is not None:
del kwargs[''instance'']
super(Myform, self).__init__(*args, **kwargs)
Ahora puede acceder a la instancia self.instance en cualquier método de limpieza en form.py
queso fresco de cheesebaker @ pypi: django-requestprovider
ACTUALIZADO 25/10/2011 : Ahora estoy usando esto con una metaclase en lugar de método, ya que Django 1.3 muestra alguna rareza de lo contrario.
class MyModelAdmin(admin.ModelAdmin):
form = MyCustomForm
def get_form(self, request, obj=None, **kwargs):
ModelForm = super(MyModelAdmin, self).get_form(request, obj, **kwargs)
class ModelFormMetaClass(ModelForm):
def __new__(cls, *args, **kwargs):
kwargs[''request''] = request
return ModelForm(*args, **kwargs)
return ModelFormMetaClass
A continuación, anule MyCustomForm.__init__
siguiente manera:
class MyCustomForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop(''request'', None)
super(MyCustomForm, self).__init__(*args, **kwargs)
A continuación, puede acceder al objeto de solicitud desde cualquier método de ModelForm
con self.request
.