As ars and Diarmuid have pointed out, you can pass request.user into your form, and use it in validating the email. Diarmuid's code, however, is wrong. The code should actually read:
from django import forms
class UserForm(forms.Form):
email_address = forms.EmailField(
widget=forms.TextInput(
attrs={
'class': 'required'
}
)
)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(UserForm, self).__init__(*args, **kwargs)
def clean_email_address(self):
email = self.cleaned_data.get('email_address')
if self.user and self.user.email == email:
return email
if UserProfile.objects.filter(email=email).count():
raise forms.ValidationError(
u'That email address already exists.'
)
return email
Then, in your view, you can use it like so:
def someview(request):
if request.method == 'POST':
form = UserForm(request.POST, user=request.user)
if form.is_valid():
# Do something with the data
pass
else:
form = UserForm(user=request.user)
# Rest of your view follows
Note that you should pass request.POST as a keyword argument, since your constructor expects 'user' as the first positional argument.
Doing it this way, you need to pass user as a keyword argument. You can either pass request.POST as a positional argument, or a keyword argument (via data=request.POST).
As ars and Diarmuid have pointed out, you can pass request.user into your form, and use it in validating the email. Diarmuid's code, however, is wrong. The code should actually read:
from django import forms
class UserForm(forms.Form):
email_address = forms.EmailField(
widget=forms.TextInput(
attrs={
'class': 'required'
}
)
)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(UserForm, self).__init__(*args, **kwargs)
def clean_email_address(self):
email = self.cleaned_data.get('email_address')
if self.user and self.user.email == email:
return email
if UserProfile.objects.filter(email=email).count():
raise forms.ValidationError(
u'That email address already exists.'
)
return email
Then, in your view, you can use it like so:
def someview(request):
if request.method == 'POST':
form = UserForm(request.POST, user=request.user)
if form.is_valid():
# Do something with the data
pass
else:
form = UserForm(user=request.user)
# Rest of your view follows
Note that you should pass request.POST as a keyword argument, since your constructor expects 'user' as the first positional argument.
Doing it this way, you need to pass user as a keyword argument. You can either pass request.POST as a positional argument, or a keyword argument (via data=request.POST).
Here's the way to get the user in your form when using generic views:
In the view, pass the request.user to the form using get_form_kwargs:
class SampleView(View):
def get_form_kwargs(self):
kwargs = super(SampleView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
In the form you will receive the user with the __init__ function:
class SampleForm(Form):
def __init__(self, user, *args, **kwargs):
super(SampleForm, self).__init__(*args, **kwargs)
self.user = user
I have some sample code from a recent project of mine that I believe may help you. In this example, super users can edit every field, while everyone else has the "description" field excluded.
Note that I think it's expected that you return a Form class from get_form, which could be why yours was not working quite right.
Here's the example:
class EventForm(forms.ModelForm):
class Meta:
model = models.Event
exclude = ['description',]
class EventAdminForm(forms.ModelForm):
class Meta:
model = models.Event
class EventAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
return EventAdminForm
else:
return EventForm
admin.site.register(models.Event, EventAdmin)
I have no idea why printing the property doesn't give you want you just assigned (I guess may be that depends on where you print, exactly), but try overriding get_fieldsets instead. The base implementation looks like this:
def get_fieldsets(self, request, obj=None): if self.declared_fieldsets: return self.declared_fieldsets form = self.get_formset(request).form return [(None, {'fields': form.base_fields.keys()})]
I.e. you should be able to just return your tuples.
EDIT by andybak. 4 years on and I found my own question again when trying to do something similar on another project. This time I went with this approach although modified slightly to avoid having to repeat fieldsets definition:
def get_fieldsets(self, request, obj=None):
# Add 'item_type' on add forms and remove it on changeforms.
fieldsets = super(ItemAdmin, self).get_fieldsets(request, obj)
if not obj: # this is an add form
if 'item_type' not in fieldsets[0][1]['fields']:
fieldsets[0][1]['fields'] += ('item_type',)
else: # this is a change form
fieldsets[0][1]['fields'] = tuple(x for x in fieldsets[0][1]['fields'] if x!='item_type')
return fieldsets
python - Creating forms with method="get" in django - Stack Overflow
python - How to get value from form field in django framework? - Stack Overflow
Django form as GET - Stack Overflow
get_form() not working on a Dynamic Form
Videos
Using a form in a view pretty much explains it.
The standard pattern for processing a form in a view looks like this:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
print form.cleaned_data['my_form_field_name']
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
Take your pick:
def my_view(request):
if request.method == 'POST':
print request.POST.get('my_field')
form = MyForm(request.POST)
print form['my_field'].value()
print form.data['my_field']
if form.is_valid():
print form.cleaned_data['my_field']
print form.instance.my_field
form.save()
print form.instance.id # now this one can access id/pk
Note: the field is accessed as soon as it's available.
I have a form with a single CharField: pages = forms.CharField()
I'm then rendering that form on the frontend but using JavaScript to duplicate the field so a user can clone that field x amount of times on the frontend. When the user submits it I'm only able to get the last field using the below:
def post(self, request):
form = self.get_form()
print(form)I think the issue is caused because form setup in Django only has a single field but when it's been submitted then there are more than 1 so self.get_form() is only getting the last field?
When I print(request.__dict__) I can see that all fields are being posted
'_post': <QueryDict: {'pages': ['a', 'b', 'c']}>
I'm not sure how to go about solving this issue. I could just extract the submission from the above QueryDict but then I won't be able to do: if form.is_valid()
Any advice on how I should tackle this issue? Should I just get it from the _post since it's just a CharField()? I'm still learning so I'd rather implement a proper solution than a hacky one.