Я пытаюсь request.user для метода чистой формы, но как я могу получить доступ к объекту запроса? Могу ли я изменить метод clean, чтобы разрешить ввод переменных?
Как получить доступ к объекту запроса или любой другой переменной в методе clean() формы?
Ответ 1
Ответ Бер - хранение его в threadlocals - очень плохая идея. Нет абсолютно никаких оснований для этого.
Гораздо лучший способ - переопределить метод формы __init__
, чтобы взять дополнительный аргумент ключевого слова, request
. Он хранит запрос в форме, где он требуется, и откуда вы можете получить к нему доступ по вашему чистому методу.
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 ...
и на ваш взгляд:
myform = MyForm(request.POST, request=request)
Ответ 2
ОБНОВЛЕНО 10/25/2011: теперь я использую это с метаклассом вместо метода, поскольку Django 1.3 отображает некоторую странность в противном случае.
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
Затем переопределите MyCustomForm.__init__
следующим образом:
class MyCustomForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(MyCustomForm, self).__init__(*args, **kwargs)
Затем вы можете получить доступ к объекту запроса из любого метода ModelForm
с помощью self.request
.
Ответ 3
Для чего стоит, если вы используете Class Based Views, вместо представлений, основанных на функциях, переопределите get_form_kwargs
в своем редактирование. Пример кода для пользовательского CreateView:
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
Вышеуказанный код представления сделает request
доступным как один из аргументов ключевого слова в функцию конструктора __init__
. Поэтому в ModelForm
do:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
# important to "pop" added kwarg before call to parent constructor
self.request = kwargs.pop('request')
super(MyModelForm, self).__init__(*args, **kwargs)
Ответ 4
Обычным aproach является сохранение объекта запроса в локальной ссылке с использованием промежуточного программного обеспечения. Затем вы можете получить доступ к этому из любого приложения, включая метод Form.clean().
Изменение подписи метода Form.clean() означает, что у вас есть собственная модифицированная версия Django, которая может быть не такой, какой вы хотите.
Благодарим middleware count что-то вроде этого:
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
Зарегистрируйте это промежуточное программное обеспечение, как описано в Django docs
Ответ 5
Я столкнулся с этой конкретной проблемой при настройке администратора. Я хотел, чтобы определенное поле проверялось на основе определенных учетных данных администратора.
Так как я не хотел изменять представление, чтобы передать запрос в качестве аргумента в форму, следующее: что я сделал:
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
Ответ 6
Для администратора Django, в 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
Ответ 7
Вы не всегда можете использовать этот метод (и его, вероятно, плохую практику), но если вы используете только форму в одном представлении, вы можете использовать ее внутри самого метода представления.
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")
Ответ 8
свежий сыр из сырбакера @pypi: django-requestprovider
Ответ 9
Ответ Daniel Roseman по-прежнему остается лучшим. Однако я бы использовал первый позиционный аргумент для запроса вместо аргумента ключевого слова по нескольким причинам:
- Вы не рискуете переопределить kwarg с тем же именем
- Запрос является необязательным, что неверно. В этом контексте атрибут запроса никогда не должен быть ничем.
- Вы можете чисто передать аргументы и kwargs родительскому классу, не изменяя их.
Наконец, я бы использовал более уникальное имя, чтобы избежать переопределения существующей переменной. Таким образом, Модный измененный ответ выглядит так:
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 ...
Ответ 10
У меня есть другой ответ на этот вопрос в соответствии с вашим требованием, которое вы хотите получить от пользователя в чистый метод формы. Вы можете попробовать это. 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)
Теперь вы можете получить доступ к self.instance в любом чистом методе в form.py