Django how to pass value from template to view - python

i want this functionality. User enters email address, and somehow it has to be passed to my views.py file, so i could then email the user that he has succesfully registered.
This is my template file:
{% extends "base.html" %}
{% block content %}
<section>
<h2 style="text-align: center">Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="submit" value="Register" onclick="validateForm()"/>
</form>
</section>
{% endblock %}
this is my forms.py file:
class MyRegistrationForm(UserCreationForm):
#kokie fields bus displayed html form
email = forms.EmailField(required=True)
firstname = forms.CharField(required=True)
lastname = forms.CharField(required=True)
whoinvitedyou = forms.CharField(required=True)
phone = forms.CharField(required=True)
workplace = forms.CharField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2', 'firstname', 'lastname', 'whoinvitedyou', 'phone', 'workplace')
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.set_password(self.cleaned_data["password1"])
#more fields for name last name
user.firstname = self.cleaned_data['firstname']
user.lastname = self.cleaned_data['lastname']
user.whoinvitedyou = self.cleaned_data['whoinvitedyou']
user.phone = self.cleaned_data['phone']
user.workplace = self.cleaned_data['workplace']
if commit:
user.save()
return user
this is my views.py:
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
else:
return render_to_response('invalid_reg.html')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
print args
return render_to_response('register.html', args)
how do i pass the value so later i can use it? maybe somebody can help me with this...

In your view, after the form.is_valid() call, the email address will be available in form.cleaned_data['email']. You can use that to send the email after form.save().
Additionally, you might want to look into existing 3rd party libraries like django-registration as it already does the functionality (emailing the just registered user) that you want.

In order to send an e-mail you don't necessarily need to send the value to a view in views.py.
You can use a post_save signal to send an email. You can put the code anywhere, although I usually put it in models.py.
Info on signals: https://docs.djangoproject.com/en/1.7/topics/signals/
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.mail import send_mail
#receiver(post_save, sender=User)
def my_handler(sender, instance, *args, **kwargs):
send_mail('Subject of email', 'Message body.', 'from#example.com', [instance.email], fail_silently=False)
note that instance.email is the email address of the user which you just saved, you can access instance to retreive more information e.g. the name, so that you can put "dear "+instance.name at the beginning of the body for example

Related

Django - After Register, Data Should Go To 2 Different Tables (Customer & User)

I am creating an e-commerce website where people can choose to login or not but still the can order and checkout (even if you are an AnonymousUser or Guest user). Now, I am making a login and register form in my website. The login form works and looks good but the register form wasn't working and throwing an error that said "RelatedObjectDoesNotExist at / User has no customer."
I think the reason is that when I register, it only makes a User in database but didn't register anything in the Customer table (which consists Name and Email). How can I register a Customer and User at the same time when I hit the "Submit" button? And how can I make that specific User have "Staff status" only and cannot make changes in the Admin site?
Also, I want to add new fields in the Register form for Name and Email that will go directly to the Customer table. I tried to do this one but it doesn't work and throwed and error that says "django.core.exceptions.FieldError: Unknown field(s) (name) specified for User".
Here's what I did:
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import *
class CustomUserCreationForm(UserCreationForm):
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
class Meta:
model = User
fields = ['username', 'name', 'email', 'password1', 'password2']
SUMMARY:
I want to add extra fields in the Register form called Name and Email. Then after clicking the Register form, I want create User and Customer at the same time. But the User should only have "Staff status" and cannot make changes in the Admin site. And the Name and Email field should go to Customer Table with the User I've created.
Here's the screenshot of my Register form:
Here's my forms.py file:
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'password1', 'password2']
def __init__(self, *args, **kwargs):
super(CustomUserCreationForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs.update({'class':'form-control','placeholder':'Enter Username'})
self.fields['password1'].widget.attrs.update({'class':'form-control','placeholder':'Enter Password'})
self.fields['password2'].widget.attrs.update({'class':'form-control','placeholder':'Confirm Password'})
Here's my views.py file:
def loginUser(request):
page = 'login'
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
print('USER:', user)
if user is not None:
login(request, user)
return redirect('/')
return render(request, 'store/login_register.html', {'page': page})
def logoutUser(request):
logout(request)
return redirect('/')
def registerUser(request):
page = 'register'
form = CustomUserCreationForm()
if request.method == "POST":
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.save()
user = authenticate(request, username=user.username, password=request.POST['password1'])
if user is not None:
login(request, user)
return redirect('/')
context = {'form': form, 'page': page}
return render(request, 'store/login_register.html', context)
Here's my models.py file:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
Here's my register.html file:
<form class="form" method="POST">
{% csrf_token %}
<h2> REGISTER </h2>
<h4> Create your account now! </h4>
<br />
{% for field in form %}
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">{{field.label}}:</label>
{{field}}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
<br />
<p> Already have an account? Login here </p>
</form>

Django 1.9 check if email already exists

My site is set up so there is no username (or rather user.username = user.email). Django has an error message if a user tries to input a username that is already in the database, however since I'm not using a username for registration I can't figure out how to do this.
Just like the default settings already is, I don't want to reload the page to find out if there is an email address already associated with a user. My guess is to use Ajax, but I can't figure out how to do it. Ive looked at other posts, but there doesn't seem to be anything recent.
How can I check to see if an email address already exists, and if so, give an error message for the user to input a new email address?
models.py:
class MyUsers(models.Model):
user = models.OneToOneField(User)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
email = models.EmailField(max_length=100, blank=True, unique=True)
company = models.CharField(max_length=100, blank=True, null=True)
website = models.URLField(max_length=100, blank=True, null=True)
phone_number = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.user.username
forms.py:
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('email',)
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('first_name', 'last_name', 'company', 'website', 'phone_number')
views.py:
def index(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.password = ""
user.username = user.email
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.email = user.email
profile.save()
user.first_name = profile.first_name
user.last_name = profile.last_name
user.save()
registered = True
return HttpResponseRedirect(reverse('registration'))
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm1()
context = {'user_form': user_form, 'profile_form': profile_form, 'registered': registered}
return render(request, 'mysite/register.html', context)
register.html:
{% extends 'mysite/base.html' %}
{% load staticfiles %}
{% block title_block %}
Register
{% endblock %}
{% block head_block %}
{% endblock %}
{% block body_block %}
<form id="user_form" method="post" action="/mysite/" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<input type="submit" name="submit" value="Register" />
</form>
{% endblock %}
You can override the clean_<INSERT_FIELD_HERE>() method on the UserForm to check against this particular case. It'd look something like this:
forms.py:
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('email',)
def clean_email(self):
# Get the email
email = self.cleaned_data.get('email')
# Check to see if any users already exist with this email as a username.
try:
match = User.objects.get(email=email)
except User.DoesNotExist:
# Unable to find a user, this is fine
return email
# A user was found with this as a username, raise an error.
raise forms.ValidationError('This email address is already in use.')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('first_name', 'last_name', 'company', 'website', 'phone_number')
You can read more about cleaning specific fields in a form in the Django documentation about forms.
That said, I think you should look into creating a custom user model instead of treating your User Profile class as a wrapper for User.

Why my django registration form does not pass is_valid()

I am new to Django and was following a tutorial on how to build a register view. I did exactly the same but my form does not pass form.is_valid().
Here is what I did:
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
user = form.save()
return HttpResponseRedirect('/accounts/register_success')
form = MyRegistrationForm()
return render(request, 'register.html', {'form':form})
def register_success(request):
return render(request, 'register_success.html')
register.html
{% extends "base.html" %}
{% block content %}
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Register" />
</form>
{% endblock %}
When I tried to register new users on the webpage, none of them passed. Even when I used username: testuser email: testuser#example.com password:testuser123, it failed. So what is wrong?
Thanks in advance!
You should follow the correct view pattern. Put the line form = MyRegistrationForm() inside an else block, then the page itself will tell you why the form is not valid.

Cannot populate django generated form in html template

I am trying to use django's form module to create and display a form. The following code I have executes without errors but an HTML form is not populated.
I have made sure that I am loading correct template. I also am certain that correct view is triggered when I go to a certain URL. I am posting some relevant code below from views, model, forms, and template files. I did debugging for quite a bit by trial-and-error but could not get to the root of issue.
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from app.forms import RegistrationForm
def registration(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
pass
else:
''' user is not submitting the form, show them a blank registration form '''
form = RegistrationForm()
context = {'form': form}
return render_to_response('register.html', context, context_instance=RequestContext(request))
register.html
{% extends "base.html" %}
{% block content %}
<form action="/register/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
form.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from app.models import Agent
class RegistrationForm(ModelForm):
username = forms.CharField( label=(u'User Name'), required=True )
first_name = forms.CharField( label=(u'First Name'), required=True )
last_name = forms.CharField( label=(u'Last Name'), required=True )
birthday = forms.DateField( label=(u'Date of birth'), required=True )
email = forms.EmailField( label=(u'Email Address'), required=True )
password = forms.CharField( label=(u'Password'), widget=forms.PasswordInput(render_value=False), required=True )
password_confirm = forms.CharField( label=(u'Confirm Password'), widget=forms.PasswordInput(render_value=False), required=True )
class Meta:
model = Agent
#exclude = ['username',]
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("That username is already taken, please select another.")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password_confirm']:
raise forms.ValidationError("The passwords did not match. Please try again.")
return self.cleaned_data
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class Agent(models.Model):
username = models.OneToOneField(User)
birthday = models.DateField()
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
def __unicode__(self):
return self.last_name + ", " + self.first_name
Had to add content block ref in base.html
{% block content %}
{% endblock %}

Anonymous User - Displaying User Information

I am trying to display my users information but I am getting anonymous user as my output;
Anonymous User
My code in my views.py is as follows;
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('/account')
else:
form = RegistrationForm()
args = {'form' : form}
return render(request, 'accounts/register.html', args)
def view_profile(request):
args = {'user': request.user}
return render (request, 'accounts/profile.html',args)
I am over-riding the UserCreationForm, my code in forms.py is;
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = {
'username',
'first_name',
'last_name',
'email',
'password1',
'password2'
}
def save(self,commit=True):
user = super(RegistrationForm,self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
My profile.html where I want my profile information to be displayed is;
{% block head %}
<title> User Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<p>
<h1> {{user}}</h1>
<h3>First Name: {{user.first_name}}</h3>
<h3>Last Name: {{user.last_name}}</h3>
<h3>Email: {{user.email}}</h3>
</p>
</div>
{% endblock %}
Really not sure where I am going wrong any help is greatly appreciated.
you must decorate your def view_profile(request): with #login_required, otherwise Django will serve this request also to Anonymous users.
Also note that if you have (or add) django.core.context_processors.request to your settings.TEMPLATE_CONTEXT_PROCESSORS
(or settings.TEMPLATES['OPTIONS']['context_processors'] depending your django version) you can use {{request.user}} in your template without create specific entry in context.

Categories