I am a self learned programmer (beginner) trying to write a Signup Class Based View. Through some tutorials I have been able to write a code which as follows:
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.views import generic
from django.views.generic import View
from .forms import UserForm
class UserFormView (View):
form_class = UserForm
template_name = "signup.html"
#display signup blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
#cleaned (normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
# Returns User objects if credentials are correct
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect("home")
return render(request, self.template_name, {'form': form})
Here is the forms.py:
from django.contrib.auth.models import User
from django import forms
class UserForm (forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password' ]
Now, I have a signup.html page designed using bootstrap. I am now stuck how to integrate my views to the html page. Using {{ form }} in a plane html is working bt not in bootstrap designed page. Please help
signup.html:
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3" style="margin-top: 70px">
<form role="form" method="post" action="">{% csrf_token %}
<h2>Welcome to Artivism <small>Sign up</small></h2>
<hr class="colorgraph" style="height: 7px; border-top: 0; background: grey; border-radius: 5px;">
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6">
{% for field in form %}
<div class="form-group">
<input type="text" name="first_name" id="first_name" class="form-control input-lg" placeholder="First Name" tabindex="1" value="{{User.first_name}}">
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
<input type="text" name="last_name" id="last_name" class="form-control input-lg" placeholder="Last Name" tabindex="2" value="{{User.last_name}}">
</div>
</div>
</div>
<div class="form-group">
<input type="text" name="user name" id="user_name" class="form-control input-lg" placeholder="User Name" tabindex="3" value="{{User.username}}">
</div>
<div class="form-group">
<input type="email" name="email" id="email" class="form-control input-lg" placeholder="Email Address" tabindex="4" value="{{User.email}}">
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password" tabindex="5" value="{{User.password}}">
</div>
</div>
<span class="help-block">By clicking Sign Up, you agree to our Terms and that you have read our Data Use Policy, including our Cookie Use.</span>
<hr class="colorgraph" style="height: 7px; border-top: 0; background: grey; border-radius: 5px;"">
<div class="row">
<div class="col-xs-12 col-md-6 col-md-offset-3"><input type="submit" value="Sign Up" class="btn btn-primary btn-block btn-lg"></div>
</div>
</form>
</div>
Include the following form in your signup.html page and let me know if it works for you:
<form method="post" action="{% url 'signup' %}" class="form-horizontal">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label" for="id_{{ field.name }}">{{ field.label }}</label>
<div class="col-sm-10">
<input class="form-control" type="{{ field.field.widget.input_type }}"
name="{{ field.name }}"
id="id_{{ field.name }}"
value="{{ field.value }}" >
</div>
</div>
{% endfor %}
<input type="submit" value="Sign Up" class="btn btn-primary pull-right">
</form>
In your case, the simple solution would be to replace your form inputs with the following ones (this should work if your form fields are ['first_name', 'last_name', 'username', 'email', 'password']):
<input type="text" name="first_name" id="id_first_name" class="form-control input-lg" placeholder="First Name" tabindex="1">
<input type="text" name="last_name" id="id_last_name" class="form-control input-lg" placeholder="Last Name" tabindex="2">
<input type="text" name="username" id="id_username" class="form-control input-lg" placeholder="Username" tabindex="3">
<input type="email" name="email" id="id_email" class="form-control input-lg" placeholder="Email Address" tabindex="4">
<input type="password" name="password" id="id_password" class="form-control input-lg" placeholder="Password" tabindex="5">
Related
RuntimeError at /signup
You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/signup/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
I got this problem while using forms. Please help
I have used bootstrap for styling
<form action="/signup/" method = "post" >
{% csrf_token %}
<div class="input-group mb-3">
<span class="input-group-text" id="basic-addon1">#</span>
<input type="text" class="form-control" placeholder="Username" name = "username" aria-label="Username" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Firstname" name="fname" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Lastname" name="lname" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
<input type="email" class="form-control" placeholder="Recipient's email" name="email" aria-describedby="basic-addon2">
<span class="input-group-text" id="basic-addon2">#gmail.com</span>
</div>
<div class="input-group mb-3">
<input type="password" placeholder="password" name = "password" class="form-control">
</div>
<div class="input-group mb-3">
<input type="password" placeholder="confirm password" name = "con_password" class="form-control">
</div>
<div class="input-group mb-3">
<button type="submit" class="btn btn-primary">Signup</buttpn>
</div>
</form>
</div>
Views.py
def signup(request):
if (request.method == "POST"):
username = request.POST.get("username")
fname = request.POST.get("fname")
lname = request.POST.get("lname")
email = request.POST.get("email")
password = request.POST.get("password")
con_password = request.POST.get("con_password")
User.objects.create_user(username=username, first_name=fname, last_name=lname, email=email, password=password)
User.save()
messages.success(request, "Account created successfully")
return redirect("login")
Should Redirect to login Page
Either add APPEND_SLASH=False in settings.py. Or change form action="/signup/" to form action="/signup"
I'm using a FormSet with crispy, and have but a submit button on each row, however hitting submit does not update records currently.
I've searched and found some similar answers which suggest the submit isn't inside the form, but mine are. Also that a form action is missing, but none of my other crispy forms have actions and they work without issue.
Are there any other reasons seen from the code below that would cause the records to not save?
forms.py
class ChangeGroupForm(FormHelper):
def __init__(self, *args, **kwargs):
super(ChangeGroupForm, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.css_class = 'form-inline'
self.form_id = 'changegroup_form'
self.form_show_labels = False
self.layout = Layout(
Div(
Div(
Div(
Field('group', placeholder='Group', css_class="form-control mb-2 mr-sm-2"),
css_class='col-lg-3'
),
Div(
Field('gps', placeholder='gps coords', css_class="form-control mb-2 mr-sm-2"),
css_class='col-lg-8'
),
Div(
HTML("""<input type="submit" name="submit" value="Save" class="btn btn-primary mt-1"/>"""),
css_class='col-lg-1'
),
css_class='row'
),
)
)
self.render_required_fields = True
views.py
#login_required
def db_change_groups(request):
change_form = modelformset_factory(ChangeGroup, fields=('group','gps'))
change_form_helper = ChangeGroupForm()
return render(request, 'home/db_change_groups.html', {
"change_form": change_form,
"change_form_helper": change_form_helper,
})
template.html
{% crispy change_form change_form_helper %}
rendered html
<form id="changegroup_form" method="post"> <input type="hidden" name="csrfmiddlewaretoken"
value="7v0000CPl3G70M6HLfF2FAiwefdfsdgdfwewdf7Gp4nay1hFqZ1Y34SBUA000mHBZQ54">
<div> <input type="hidden" name="form-TOTAL_FORMS" value="10" id="id_form-TOTAL_FORMS"> <input type="hidden"
name="form-INITIAL_FORMS" value="9" id="id_form-INITIAL_FORMS"> <input type="hidden"
name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS"> <input type="hidden"
name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS"> </div>
<div>
<div class="row">
<div class="col-lg-3">
<div id="div_id_form-0-group" class="form-group">
<div class="controls "> <input type="text" name="form-0-group" value="A" maxlength="50"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="Group"
id="id_form-0-group"> </div>
</div>
</div>
<div class="col-lg-8">
<div id="div_id_form-0-gps" class="form-group">
<div class="controls "> <input type="text" name="form-0-gps" maxlength="255"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="gps coords"
id="id_form-0-gps"> </div>
</div>
</div>
<div class="col-lg-1"> <input type="submit" name="submit" value="Save" class="btn btn-primary mt-1" />
</div>
</div>
</div> <input type="hidden" name="form-0-id" value="1" id="id_form-0-id">
<div>
<div class="row">
<div class="col-lg-3">
<div id="div_id_form-1-group" class="form-group">
<div class="controls "> <input type="text" name="form-1-group" value="B" maxlength="50"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="Group"
id="id_form-1-group"> </div>
</div>
</div>
<div class="col-lg-8">
<div id="div_id_form-1-gps" class="form-group">
<div class="controls "> <input type="text" name="form-1-gps" maxlength="255"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="gps coords"
id="id_form-1-gps"> </div>
</div>
</div>
<div class="col-lg-1"> <input type="submit" name="submit" value="Save" class="btn btn-primary mt-1" />
</div>
</div>
</div>
</div> <input type="hidden" name="form-9-id" id="id_form-9-id">
</form>
You need to attach somthing like this to your view
def db_change_groups(request):
....
if request.method == "POST":
form = ChangeGroupForm(request.POST)
if form.is_valid():
# Access cleaned data with
group = form.cleaned_data['group']
# Then you can save this to a model.
# return success template or something
else:
# Check for errors.
If you created the form with ModelForm instead of FormHelper you could use form.save() which you automatically save it to the model.
After POST method signup page always redirects to same page without printing any message or redirecting to homepage or login page but I am tracing it in every steps by printing something to check how it is working. But I can signup a new user using python shell.
Terminal is giving me only this:
[28/Nov/2019 15:36:26] "GET / HTTP/1.1" 200 2574
[28/Nov/2019 15:36:46] "POST / HTTP/1.1" 200 2574
def signup(request):
if request.user.is_authenticated:
return render(request,'/',{})
form = UserForm(request.POST or None)
if request.method == 'POST':
print("step 2")
if form.is_valid():
user = form.save(commit= False)
username= form.cleaned_data['username']
password= form.cleaned_data['password']
user.set_password(password)
user.save()
authenticate(username= username, password= password)
Profile.objects.create(
user= user,
full_name=form.cleaned_data['full_name'],
codeforces_id= form.cleaned_data['codeforces_id'],
Uva_Id = form.cleaned_data['Uva_Id'],
points = 0,
department= form.cleaned_data['department']
)
if user is not None:
if user.is_active:
login(request,user)
return redirect('/')
return render(request, 'signup.html',{'msg':'Invalid'})
else:
error = form.errors
print("error step")
return render(request, 'signup.html',{'msg':error})
else:
return render(request,'signup.html',{})
forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget= forms.PasswordInput)
full_name = forms.CharField(required= True)
codeforces_id = forms.CharField(required= True)
Uva_Id = forms.CharField(required= True)
department = forms.CharField(required= True)
class Meta:
model = User
fields=('username','email','password','full_name','codeforces_id','Uva_Id','department')
signup.html:
<body>
<div class="wrapper">
<div class="inner" style="width: 500px;">
{% block content %}
<form action="" method="post" style="padding-top: 40px; padding-bottom: 50px">
{% csrf_token %}
<h3 style="margin-bottom: 20px">New Account?</h3>
<div class="form-group">
<label for="username" class="control-label">Username</label>
<input type="text" class="form-control" name="username" placeholder="username">
</div>
<div class="form-group">
<label for="email" class="control-label">Email</label>
<input type="text" class="form-control" name="email" placeholder="Email">
</div>
<div class="form-group">
<label for="password" class="control-label">password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
<div class="form-group">
<label for="full_name" class="control-label">fullname</label>
<input type="text" class="form-control" name="full_name" placeholder="Full Name">
</div>
<div class="form-group">
<label for="codeforces_id" class="control-label">codeforces_id</label>
<input type="text" class="form-control" name="codeforces_id" placeholder="codeforces_id">
</div>
<div class="form-group">
<label for="Uva_Id" class="control-label">Uva_Id</label>
<input type="text" class="form-control" name="Uva_Id" placeholder="uva_id">
</div>
<div class="form-group">
<label for="department" class="control-label">department</label>
<input type="text" class="form-control" name="department" placeholder="department">
</div>
<button type="submit" style="margin-top:20px">
<span>Register</span>
</button>
<p style="color: red">{{ msg }}</p>
<a style="float: right" href="/login">Already have an account</a>
</form>
{% endblock %}
</div>
</div>
</body>
Updated:
url.py
urlpatterns = [
url(r'^$',views.index,name='index'),
url(r'^login/$',views.Login,name= 'Login'),
url(r'^signup/$',views.signup,name='signup'),
url(r'^logout/$',views.Logout,name='logout'),
You havent included the url that the form should hit on POST
[...]
<form action="{% url 'name-of-the-url-that-leads-to-your-view' %}" method="post" style
[...]
i'm green hand to django, when i try to use the usersignupform, the request post is like
`<QueryDict: {'csrfmiddlewaretoken': ['Wxlj42vbyAweKevBeSs5TvGj1ot8tJknUOGzmlKCphs5cDnqvsmriCSK9wYDuAof'], 'username': ['dulong11'], 'email': ['stephen.du#abc.com'], 'password1': ['dulong'], 'password2': ['dulong'], 'submit': ['']}`
then the usercreationform.is_valid() will always return false, i do not know why, and how it happens? why it cannot work??
form.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class UserSignUpForm(UserCreationForm):
#username = forms.CharField()
email = forms.EmailField(max_length=100)
#password1 = forms.CharField()
#password2 = forms.CharField()
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
view.py i tried to use usersignupform for create a new user, but it just failed, and the form.is_valid() is false
form = UserSignUpForm(request.POST)
print(request.POST)
print(form.is_valid())
register.html
<form action="." method="post" id="frm" class="frm">
{% csrf_token %}
<div class="r-list">
<div class="line">
<i class="dqfont icon-mobilephone"></i>
<input type="text" name="username" placeholder="用户名" autocomplete="off">
<span class="error" id="tel_error"></span>
</div>
</div>
<div class="r-list">
<div class="line">
<i class="dqfont icon-mobilephone"></i>
<input type="email" name="email" placeholder="请输入邮箱" autocomplete="off">
</div>
<span class="error"></span>
</div>
<div class="r-list">
<div class="line">
<i class="dqfont icon-pass"></i>
<input type="password" name="password1" placeholder="请输入密码" autocomplete="off">
</div>
<span class="error"></span>
</div>
<div class="r-list">
<div class="line">
<i class="dqfont icon-pass"></i>
<input type="password" name="password2" placeholder="请再次输入你的密码" autocomplete="off">
</div>
<span class="error"></span>
</div>
<div class="r-list">
<div class="protocol">
<span class="checkbox-checked" id="accept">我已阅读并同意<a href="#"
target="_blank">《IPLink用户协议》</a>和《隐私保护》</span>
</div>
</div>
<div class="r-list">
<span class="error"></span>
<!--a href="#" class="btn" id="btn">同意协议并注册</--a>-->
<button type="submit" class="btn" name="submit" id="btnSubmit"
style="width:380px">同意协议并注册</button>
</div>
</form>
form.error is like the following. problem solved, too silly, damn~
password2The password is too similar to the username.This password is too short. It must contain at least 8 characters.
I'm trying to show error message in my custom signup template. Just to verify my below codes work, I used the {{ form.as_table }} and it shows error message properly. However, when I use my custom signup template, it doesn't show any error message when I cause an error on purpose on the signup form.
HTML
<form class="form-signin" method="POST">
{% csrf_token %}
<div class="container">
<div class="jumbotron">
<a class="navbar-brand js-scroll-trigger" href="{% url 'boutique:index' %}"><img width="165" height="30" src="{% static 'boutique/img/modvisor_logo_black.png' %}"></a>
<br><br>
<div class="text-center mb-4">
<h1 class="h3 mb-3 font-weight-normal">Join Modvisor</h1>
<p class="error-message">
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
{% endif %}
</p>
</div>
<div class="form-label-group">
<input type="text" id="inputEmail" class="form-control" name="username" placeholder="Email address" required autofocus>
<label for="inputEmail">Email</label>
</div>
<div class="form-label-group">
<input type="password" id="inputPassword1" class="form-control" name="password1" placeholder="Password" required>
<label for="inputPassword">Password</label>
</div>
<div class="form-label-group">
<input type="password" id="inputPassword2" class="form-control" name="password2" placeholder="Password" required>
<label for="inputPassword">Confirm Password</label>
</div>
<!--
<div class="form-label-group">
<input type="password" id="inputPassword" class="form-control" name="password2" placeholder="Password" required>
<label for="inputPassword">Confirm Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
-->
<button class="btn btn-success btn-block" type="submit">Sign Up</button>
<br>
<button class="btn btn-secondary btn-block" type="button">Back</button>
<p class="mt-5 mb-3 text-muted text-center">© 2018 Modvisor All Rights Reserved.</p></p>
</div>
</div>
</form>
forms.py
class SignupForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
fields = UserCreationForm.Meta.fields
views.py
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
form.save()
return redirect(settings.LOGIN_URL)
else:
form = SignupForm()
return render(request, 'accounts/register.html', {'form': form})
You should use form.errors.field_name for errors related to specific field. Like for error on username field, it will be form.errors.username
You HTML will look like
<div class='error'>{{form.errors.username}}</div>
<div class="form-label-group">
<input type="text" id="inputEmail" class="form-control" name="username" placeholder="Email address" required autofocus>
<label for="inputEmail">Email</label>
</div>