I am trying to get http://areyouahuman.com/ capcha working on my site
I found
https://gist.github.com/klanestro/9572114
I subclassed it
class Turtle_Form(forms.ModelForm,AreYouHumanForm):
''' This is code to make sure the User automatically saves the
user to the database in context.
'''
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(Turtle_Form, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
return obj #<--- Return saved object to caller.
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(Turtle_Form, self).__init__(*args, **kwargs)
and
class OfertoCreateForm(Turtle_Form):
class Meta:
model = Oferto
fields = ( "name",
"description",
"tags",
"time",
"requirements",
"location",
"image",
'AreYouHumanForm',
)
but nothing comes up on the form, no errors nothing.
The field in that gist is called session_secret, which is the name you should be using in the fields tuple.
Related
I have a model which has a field 'keywords'. When I use a form to create/modify records, I am able to clean this field and then save it.
class ILProjectForm(forms.ModelForm):
class Meta:
models = ILProject
fields = '__all__'
def clean_keywords(self):
k = self.cleaned_data.get('keywords')
if k:
k = ','.join([a.strip() for a in re.sub('\\s+', ' ', k).strip().split(',')])
return k
However, I am not sure how to run clean() to update the data when I am using the list_editable option in the admin page.
I tried something like this bit I get an error saying I cannot set an attribute. What is the correct way to update the data after it has been cleaned?
class MyAdminFormSet(BaseModelFormSet):
def clean(self):
print(type(self.cleaned_data))
recs = []
for r in self.cleaned_data:
if r['keywords']:
r['keywords'] = ','.join([a.strip() for a in re.sub('\\s+', ' ', r['keywords']).strip().split(',')])
print(r['keywords'])
recs.append(r)
self.cleaned_data = recs <-- this part is problematic.
class ILProjectAdmin(...)
...
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super().get_changelist_formset(request, **kwargs)
It should be like this:
class ILProjectAdmin(...)
...
def get_changelist_form(self, request, **kwargs):
return ILProjectForm
Please refer this tip: Django: Access request object from admin's form.clean()
class ProjectRequestForm(forms.ModelForm):
class Meta:
model = ProjectRequest
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(ProjectRequestForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request.user.has_perm('access_role'):
raise ValidationError(f'No permission', code='invalid')
class ProjectRequestAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(ProjectRequestAdmin, self).get_form(request, obj, **kwargs)
class AdminFormWithRequest(form):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return form(*args, **kwargs)
return AdminFormWithRequest
def get_changelist_form(self, request, **kwargs):
class AdminFormWithRequest(ProjectRequestForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ProjectRequestForm(*args, **kwargs)
return AdminFormWithRequest
I have a Formview and pass the pk to the ModelForm. In the ModelForm i am not able to use self.pk in the queryset i define for the field:
views.py
[...]
def get_form_kwargs(self):
# Pass extra kwargs to DetailProductForm
kwargs = super(DetailProduct, self).get_form_kwargs()
kwargs.update({'pk': self.kwargs['pk']})
return kwargs
forms.py
class DetailProductForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
# get the pk from the FormView at set it as self.pk
self.pk = kwargs.pop('pk', None)
super(DetailProductForm, self).__init__(*args, **kwargs)
# use self.pk in my queryset (there are more fields who use self.pk, this is just one as an example)
field = forms.ModelChoiceField(queryset=Configuration.objects.filter(product__pk=self.pk), widget=forms.RadioSelect)
class Meta:
model = Configuration
fields = ['field']
NameError: name 'self' is not defined
How can i use self.pk for the fields?
Found a solution. I actually do not even need a ModelForm anymore.
class DetailProductForm(forms.Form):
field = forms.ModelChoiceField(queryset=None, widget=forms.RadioSelect)
def __init__(self, *args, **kwargs):
self.pk = kwargs.pop('pk', None)
super().__init__(*args, **kwargs)
self.fields['field'].queryset = Configuration.objects.filter(product__pk=self.pk))
I have some problem. I wanna take a request in django forms but it may have some problem. here is my code.
forms.py
class PostForm(forms.ModelForm):
CHOICES = request.user.fields()
receive_user = fields.MultipleChoiceField(choices=CHOICES)
content = forms.CharField(widget=PagedownWidget(show_preview=False))
publish = forms.DateField(widget=forms.SelectDateWidget)
class Meta:
model = Post
fields = [
"receive_user",
"content",
]
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(MyForm, self).__init__(*args, **kwargs)
and views.py
def post_create(request):
if not request.user.is_authenticated():
raise Http404
form = PostForm(request.POST or None, request=request)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
and error message is
NameError: name 'request' is not defined
request is passed to the __init__ method and is therefore only available there. You can't use it at module level because it's not defined there; and you wouldn't want to, anyway, because anything at module level is run once when the class is first imported, not when the form is instantiated.
But since you do have it within init, you should use it there:
class PostForm(forms.ModelForm):
receive_user = fields.MultipleChoiceField(choices=())
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(MyForm, self).__init__(*args, **kwargs)
self.fields['receive_user'].choices = request.user.....
(Note, I doubt that .fields() is what you want there, but never mind.)
In my implementation of ModelForm, I would like to perform different types of validation checks based on whether current user is superuser. How can I access the current request user?
If you're using Class Based Views (CBVs) then passing an extra argument in the form constructor (e.g. in get_forms_class) or in form_class will not work, as <form> object is not callable will be shown.
The solution for CBVs is to use get_form_kwargs(), e.g.:
views.py:
class MyUpdateView(UpdateView):
model = MyModel
form_class = MyForm
# Sending user object to the form, to verify which fields to display/remove (depending on group)
def get_form_kwargs(self):
kwargs = super(MyUpdateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
forms.py:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user') # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
super(MyForm, self).__init__(*args, **kwargs)
# If the user does not belong to a certain group, remove the field
if not self.user.groups.filter(name__iexact='mygroup').exists():
del self.fields['confidential']
you can pass the user object as an extra argument in the form constructor.
e.g.
f = MyForm(user=request.user)
and the constructor will look like:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user',None)
super(MyForm, self).__init__(*args, **kwargs)
and then use user in the clean_XX forms as you wish
My small addition,
I had a requirement where one of the model choice fields of the form is dependent on the request.user, and it took a while to take my head around.
The idea is that
you need to have a __init__ method in the model form class,
and you access the request or other parameters from the arguments of the __init__ method,
then you need to call the super constructor to new up the form class
and then you set the queryset of the required field
code sample
class CsvUploadForm(forms.Form):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(CsvUploadForm, self).__init__(*args, **kwargs)
self.fields['lists'].queryset = List.objects.filter(user=user)
lists = forms.ModelChoiceField(queryset=None, widget=forms.Select, required=True)
as you can see, the lists variable is dependent on the current user, which is available via request object, so we set the queryset of the field as null, and its assigned dynamically from the constructor later.
Take a look into the order of the statements in the above code
you can pass the user variable like this from the view file
form = CsvUploadForm(user=request.user)
or with other POST, FILE data like below
form = CsvUploadForm(request.POST, request.FILES, user=request.user)
You may reference the user object using the instance attribute within the instance it self.
Ex; self.instance.user
class StatusForm(ModelForm):
# def __init__(self, *args, **kwargs):
# self.user = kwargs.pop('user', None)
# super(StatusForm, self).__init__(*args, **kwargs)
class Meta:
model = Status
fields = [
'user',
'content',
'image'
]
def clean_content(self):
content = self.cleaned_data.get("content", None)
if len(content) > 240:
raise ValidationError(f"Hey {self.instance.user.username}, the content is too long")
return content
This worked for me, when I am not sending form in context explicitly in get_context_data:
views.py
class MyView(FormView):
model = MyModel
form_class = MyForm
def get_form_kwargs(self):
kwargs = super(MyView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
form.py
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(MyForm, self).__init__(*args, **kwargs)
if not self.user.groups.filter(name__iexact='t1_group').exists():
del self.fields['test_obj']
When sending form explicitly in get_context_data we can use and this is forms.Form :
views.py
class MyView(FormView):
model = MyModel
form_class = MyForm
def get_context_data(self, **kwargs):
context = super(MyView, self).get_context_data(**kwargs)
context['form'] = self.form_class(self.request.user)
return context
forms.py
class MyForm(forms.Form):
def __init__(self, user,*args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
if not user.groups.filter(name__iexact='t1_group').exists():
del self.fields['test_obj']
I am using the django 1.3 on trunk, and start learning about class views.
I had this:
class Project(models.Model):
title = models.CharField(max_length=90)
slug = models.CharField(max_length=90)
description = models.TextField()
owner = models.ForeignKey(User)
class ProjectForm(ModelForm):
class Meta:
model = Project
exclude = ('owner',)
widgets = {
'description': Textarea(attrs={'cols': 40, 'rows': 20}),
}
class ProjectCreateView(CreateView):
model = Project
form_class = ProjectForm
def get(self, request, *args, **kwargs):
return super(ProjectCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return super(ProjectCreateView, self).post(request, *args, **kwargs)
I am trying, to get a form using model forms from django excluding the owner field, to get the field value after with the request.user property.
The form as it is, works. But how can make sure the ModelForm use request.user for the Project.owner field?
My first guess, was to override get_form_kwargs method from the view
class ProjectCreateView(CreateView):
# .....
def get_form_kwargs(self, **kwargs):
self.initial['owner': self.request.user})
kwargs = super(ProjectCreateView, self).get_form_kwargs(**kwargs)
return kwargs
But seem to have no effect on the data used by the model form
get_form_kwargs is supposed to return a dict of arguments for your form - you set self.initial, but you didn't attach it to kwargs:
def get_form_kwargs(self, **kwargs):
kwargs = super(ProjectCreateView, self).get_form_kwargs(**kwargs)
kwargs['initial']['owner'] = self.request.user
return kwargs