How to pass user object to forms in Django - python

How would I pass a user object or a request to my form for using it as an initial value for input textbox?
For example, I have my form:
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True, initial="???")
contact_email = forms.EmailField(required=True)
subjects = forms.ChoiceField(choices=emailsubjects)
content = forms.CharField(
required=True,
widget=forms.Textarea
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_email'].label = "Your email:"
self.fields['content'].label = "What do you want to say?"
self.fields['subjects'].label = "Please, select the subject of your message"
Where i want my user.first_name to be as a default value for contact_name field.
Here is my views.py, where i call for form:
def ContactsView(request):
form_class = ContactForm(request=request)
# new logic!
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
form_content = request.POST.get('content', '')
subjects = form.cleaned_data['subjects']
subjects = dict(form.fields['subjects'].choices)[subjects]
# Email the profile with the
# contact information
template = get_template('threeD/email/contact_template.txt')
context = Context({
'contact_name': contact_name,
'subjects': subjects,
'contact_email': contact_email,
'form_content': form_content,
})
content = template.render(context)
email = EmailMessage(
"New message from " + contact_name,
content,
"Message - " + subjects + ' ',
['smart.3d.printing.facility#gmail.com'],
headers={'Reply-To': contact_email}
)
email.send()
messages.success(request, "Thank you for your message.")
return redirect('/index/contacts/')
return render(request, 'threeD/contacts.html', {
'form': form_class,
})
Any help would be very much appreciated

You have changed your form to take the request object. Therefore you can access self.request.user inside your form's methods:
class ContactForm(forms.Form):
...
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_name'].initial = self.request.user.first_name
You also have to update your view to pass the request object. Remember to update the code for GET and POST requests.
if request.method == 'POST':
form = ContactForm(data=request.POST, request=request)
...
else:
# GET request
form = ContactForm(request=request)
Finally, by passing the request to the form, you have tightly coupled it to the view. It might be better to pass the user to the form instead. This would make it easier to test the form separately from the view. If you change the form, remember to update the view as well.

You need to pass the initial values in the view:
views:
def ContactsView(request):
form_class = ContactForm(request=request,
initial={'contact_name': request.user.first_name})
...

Related

Exclude Logged in User inside forms.py [duplicate]

How would I pass a user object or a request to my form for using it as an initial value for input textbox?
For example, I have my form:
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True, initial="???")
contact_email = forms.EmailField(required=True)
subjects = forms.ChoiceField(choices=emailsubjects)
content = forms.CharField(
required=True,
widget=forms.Textarea
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_email'].label = "Your email:"
self.fields['content'].label = "What do you want to say?"
self.fields['subjects'].label = "Please, select the subject of your message"
Where i want my user.first_name to be as a default value for contact_name field.
Here is my views.py, where i call for form:
def ContactsView(request):
form_class = ContactForm(request=request)
# new logic!
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
form_content = request.POST.get('content', '')
subjects = form.cleaned_data['subjects']
subjects = dict(form.fields['subjects'].choices)[subjects]
# Email the profile with the
# contact information
template = get_template('threeD/email/contact_template.txt')
context = Context({
'contact_name': contact_name,
'subjects': subjects,
'contact_email': contact_email,
'form_content': form_content,
})
content = template.render(context)
email = EmailMessage(
"New message from " + contact_name,
content,
"Message - " + subjects + ' ',
['smart.3d.printing.facility#gmail.com'],
headers={'Reply-To': contact_email}
)
email.send()
messages.success(request, "Thank you for your message.")
return redirect('/index/contacts/')
return render(request, 'threeD/contacts.html', {
'form': form_class,
})
Any help would be very much appreciated
You have changed your form to take the request object. Therefore you can access self.request.user inside your form's methods:
class ContactForm(forms.Form):
...
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_name'].initial = self.request.user.first_name
You also have to update your view to pass the request object. Remember to update the code for GET and POST requests.
if request.method == 'POST':
form = ContactForm(data=request.POST, request=request)
...
else:
# GET request
form = ContactForm(request=request)
Finally, by passing the request to the form, you have tightly coupled it to the view. It might be better to pass the user to the form instead. This would make it easier to test the form separately from the view. If you change the form, remember to update the view as well.
You need to pass the initial values in the view:
views:
def ContactsView(request):
form_class = ContactForm(request=request,
initial={'contact_name': request.user.first_name})
...

How to create a URL for templateView?

How can I write a url for a form using TemplateView. I wrote a method to validate and pass the company details through form. Using that form object that I'm trying to access the HTML fields.
Form.py
class CompanyDetailsForm(forms.Form):
class meta:
fields = ['company_name','contact_person','employee_count','email','mobile_number']
widgets = {
'comment':Textarea(attrs={'cols':30,'rows':5}),
}
company_name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'placeholder':'company Name'}))
contact_person = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'placeholder':'Contact Person'}))
email = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'placeholder':'Email'}))
employee_count = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'placeholder':'Number Of Employee'}))
mobile_number = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'placeholder':'Mobile Number'}))
View.py
class GetCompanyView(TemplateView):
template_name = "astra/company_details.html"
form = CompanyDetailsForm()
def get_context_data(self,**kwargs):
context = super().get_context_data(**kwargs)
context['form']=self.form
return context
def company_details(request):
if request.method =="POST":
form = CompanyDetailsForm(request.POST)
if form.is_valid():
company_name = form.cleaned_data['company_name']
contact_person = form.cleaned_data['contact_person']
email = form.cleaned_data['email']
employee_count = form.cleaned_data['employee_count']
mobile_number = form.cleaned_data['mobile_number']
try:
form.save()
send_mail(company_name,contact_person,email,employee_count,mobile_number,['salesastra500#gmail.com'])
except BadHeaderError:
return BadHeaderError
return render(request,'astra/company_details.html',{'form':form})
else:
return render(request,'astra/company_details.html')
I want to run my company_details.html file using TemplateView. I'm not able to write the url for same. Plz suggest
TemplateView only have get method
def get(self, request, *args, **kwargs):
return render(request,self.template_name, {'form': self.form})
if you have get and post methods use FormView

Django NameError: request is not defined in class based view [duplicate]

How do I get the current logged in user in forms.py? I am trying to pre-populate the email field of the current user.
class ContactMe(forms.Form):
name = forms.CharField(label = "Name")
email_address = forms.CharField(label = "Email Address", intital = request.user.email)
subject = forms.CharField(label = "Subject")
message = forms.CharField(label = "Message", widget=forms.Textarea(attrs={'cols': 10, 'rows': 3}))
additional_comments = forms.CharField(required = False)
class Meta:
model = Contact_me
I tried passing request from views.py as :
contact_form = ContactMe(request.POST or None, request)
and then receiving the request inside of class ContactMe as :
class ContactMe(forms.Form, request):
name = forms.CharField(label = "Name")
email_address = forms.CharField(label = "Email Address", intital = **request.user.email**)
subject = forms.CharField(label = "Subject")
message = forms.CharField(label = "Message", widget=forms.Textarea(attrs={'cols': 10, 'rows': 3}))
additional_comments = forms.CharField(required = False)
class Meta:
model = Contact_me
It throws the error NameError: name 'request' is not defined. I know request is accessible in html, models.py, views.py. How to get it in forms.py?
The views.py :
def list_posts(request):
request.session.set_expiry(request.session.get_expiry_age()) # Renew session expire time
instance_list = Post.objects.all()
register_form = UserRegisterForm(data=request.POST or None)
if register_form.is_valid():
personal.views.register_form_validation(request, register_form)
login_form = UserLoginForm(request.POST or None)
if login_form.is_valid() :
personal.views.login_form_validation(request, login_form)
feedback_form = FeedbackForm(request.POST or None)
if feedback_form.is_valid() :
personal.views.feedback_form_validation(request, feedback_form)
contact_form = ContactMe(request.POST or None, request)
if contact_form.is_valid() :
personal.views.contact_form_validation(request, login_form)
if request.POST and not(register_form.is_valid() or login_form.is_valid()):
if request.POST.get("login"):
return accounts.views.login_view(request)
else:
return accounts.views.register_view(request)
template = 'blog/archives.html'
dictionary = {
"object_list" : content,
"register_form" : register_form,
"login_form" : login_form,
"feedback_form" : feedback_form,
"contact_form" : contact_form,
}
return render(request,template,dictionary)
You are trying to pass the request when constructing the form class. At this point there is no request. The request only exists inside your view function. You should, therefore, pass the request in your view function when constructing the form instance. To prepopulate the form, you can use the initial keyword of the form constructor. It takes a dictionary of field names and values as input.
Example:
#views.py
from django.shortcuts import render
from django import forms
class TestForm(forms.Form):
foo = forms.CharField()
def test_form(request):
form = TestForm(initial=dict(foo=request.<some_property>))
context = dict(form=form)
template_name = 'testapp/test.html'
return render(request, template_name, context)
This line is wrong class ContactMe(forms.Form, request).
(Hint: request isn't a base class for your form)
The correct way is to access the user in the __init__ method of the form:
class ContactMe(forms.ModelForm):
class Meta:
model = Contact_me
fields = '__all__'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ContactMe, self).__init__(*args, **kwargs)
The corresponding line in the views.py:
contact_form = ContactMe(request.POST, user=request.user)
Also you get this error if you write requests instead of request
Example
in views.py
def all_products(requests):
products = Product.objects.all()
return render(request, 'store/home.html', {'products': products})
should be:
def all_products(request):
products = Product.objects.all()
return render(request, 'store/home.html', {'products': products})
This was my issue, that's why I bring it up.

Django clean_email function returning "enter a valid email"

I made a clean_email function in my forms.py to check if the email the person is signing up with is part of a registered school.
This is the form:
class StudentRegister(UserCreationForm):
email = forms.EmailField(required = True)
def __init__(self, *args, **kwargs):
super(StudentRegister, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs['placeholder'] = 'example#example.com'
self.fields['first_name'].widget.attrs['placeholder'] = 'First Name'
self.fields['last_name'].widget.attrs['placeholder'] = 'Last Name'
self.fields['password1'].widget.attrs['placeholder'] = 'Password'
self.fields['password2'].widget.attrs['placeholder'] = 'Password'
class Meta:
model = get_user_model()
fields = (
'email',
'first_name',
'last_name',
'password1',
'password2'
)
def clean_email(self):
email = self.cleaned_data.get('email')
email = email.split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
raise forms.ValidationError('School not found, check your email')
return email
def save(self):
user = super(StudentRegister, self).save()
student = Student(user = user)
student.save()
return user, student
This is the view for the student registration:
def student_registration(request):
#Student Registration
if request.method == 'POST':
form = StudentRegister(request.POST)
#Gets school object from email domain.
email = form['email'].value().split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
pass
if form.is_valid() and school:
user, Student = form.save()
Student.school = school
Student.save()
user.groups.add(Group.objects.get(name='Student'))
#user.is_active to stop users logging in without confirming their emails
user.is_active = False
user.save()
#Sends confirmation link.
send_confirmation_email(request, user)
args = {'email': user.email,
'link': user.Student.school.email_website,}
return render(request, 'email/token_sent.html', args)
else:
args = {'form': form,}
return render(request, 'users/students.html', args)
else:
form = StudentRegister()
args = {'form': form,}
return render(request, 'users/students.html', args)
The error that appears on the form is "Enter a valid email address." even if I enter in a valid email.
Any ideas what the problem may be?
In clean_email method you override original email with domain. Change yout code to this:
def clean_email(self):
original_email = self.cleaned_data.get('email')
email = original_email.split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
raise forms.ValidationError('School not found, check your email')
return original_email

How to request.user.is_authenticated() in views.py? Django

I am trying to check if user is logged in from my views.py file. As depending if user is logged in it should return me different forms. But request.user.is_authenticated() or request.user.is_authenticated is not working, i always get True value.
My view:
def ContactsView(request):
form_class = ContactForm_logged(request=request)
form_class_nonlogged = ContactForm_nonlogged(request=request)
# new logic!
if request.method == 'POST':
if request.user.is_authenticated():
form = ContactForm_logged(data=request.POST, request = request)
else:
form = ContactForm_nonlogged(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
form_content = request.POST.get('content', '')
subjects = form.cleaned_data['subjects']
subjects = dict(form.fields['subjects'].choices)[subjects]
# Email the profile with the
# contact information
template = get_template('threeD/email/contact_template.txt')
context = Context({
'contact_name': contact_name,
'subjects': subjects,
'contact_email': contact_email,
'form_content': form_content,
})
content = template.render(context)
email = EmailMessage(
"New message from " + contact_name,
content,
"Message - " + subjects + ' ',
['smart.3d.printing.facility#gmail.com'],
headers={'Reply-To': contact_email}
)
email.send()
messages.success(request, "Thank you for your message.")
return redirect('/index/contacts/')
else:
if request.user.is_authenticated():
form = ContactForm_logged(request=request)
else:
form = ContactForm_nonlogged()
if request.user.is_authenticated():
return render(request, 'threeD/contacts.html', {
'form': form_class,
})
else:
return render(request, 'threeD/contacts.html', {
'form': form_class_nonlogged,
})
And two of my forms:
class ContactForm_logged(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
subjects = forms.ChoiceField(choices=emailsubjects)
content = forms.CharField(
required=True,
widget=forms.Textarea
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm_logged, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
if (self.request.user.first_name == '' or self.request.user.last_name ==''):
self.fields['contact_name'].initial = 'Type your name here'
self.fields['contact_name'].widget.attrs['readonly'] = False
else:
self.fields['contact_name'].initial = self.request.user.first_name
self.fields['contact_name'].widget.attrs['readonly'] = True
self.fields['contact_email'].label = "Your email:"
if (self.request.user.profile.sdu_email == ''):
if (self.request.user.email == ''):
self.fields['contact_email'].initial = 'Type your email here'
self.fields['contact_email'].widget.attrs['readonly'] = False
else:
self.fields['contact_email'].initial = self.request.user.email
self.fields['contact_email'].widget.attrs['readonly'] = True
else:
self.fields['contact_email'].initial = self.request.user.profile.sdu_email
self.fields['contact_email'].widget.attrs['readonly'] = True
self.fields['content'].label = "What do you want to say?"
self.fields['content'].initial = "Dear, Smart 3D printing facility team, I like this WEB server very much, but ..."
self.fields['subjects'].label = "Please, select the subject of your message"
class ContactForm_nonlogged(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
subjects = forms.ChoiceField(choices=emailsubjects)
content = forms.CharField(
required=True,
widget=forms.Textarea
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ContactForm_nonlogged, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_name'].initial = 'Type your name here'
self.fields['contact_email'].label = "Your email:"
self.fields['contact_email'].initial = 'Type your email here'
self.fields['content'].label = "What do you want to say?"
self.fields['content'].initial = "Dear, Smart 3D printing facility team, I like this WEB server very much, but ..."
self.fields['subjects'].label = "Please, select the subject of your message"
The problem is that, whether i am logged in or am not i always get ContactForm_logged form back. And if i m not logged in than, getting ContactForm_logged form back i get an error, that "'AnonymousUser' object has no attribute 'first_name'".
I read on forums that that could have happened if i call request.user.is_authenticated() wrong, but i have tried both request.user.is_authenticated() and request.user.is_authenticated, both give me the same error :/
Any help would be greatly appreciated!
If you are using Django 1.10+, then you should use the property request.user.is_authenticated.
If you are using Django 1.9 or earlier, then you must use request.user.is_authenticated(). Using request.user.is_authenticated in Django 1.9 or earlier is a mistake which can cause sensitive data to be leaked, because it will always be evaluated as True.
If you are using the correct version and it is returning True, then that suggests you really are logged in.
The problem is in the first line of your view method definition:
def ContactsView(request):
form_class = ContactForm_logged(request=request)
Here you are creating an instance of ContactForm_logged class. This line will be executed every time the view method is called. So an instance of ContactForm_logged class will be created everytime, whether user is logged-in or not. Further, in the __init__ method of ContactForm_logged class you are accessing self.request.user.first_name. So when the ContactForm_logged instance is being initialized for unauthenticated requests it is raising the error: "'AnonymousUser' object has no attribute 'first_name'"

Categories

Resources