How to customize UserRegistration Form of Django? - python

I want to know how to change the display of default UserRegistrationForm.
This is my views.py file.
from django.http import *
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from django.contrib.auth.forms import UserCreationForm
from forms import MyRegistrationForm
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args)
def register_success(request):
return render_to_response('register_success.html')
This is what is displayed in templates of register_user.
{% extends "application/base.html" %}
{% block content %}
<h2> Register </h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
{% endblock %}
I want to access each and every filed of the {{form}} independently so that the it is easy to access the view.how to do it??
Also this is my forms.py file
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
Please Help me i am new to django??

You can do the following:
create appname/templates/registration-folder
In this folder, put all the html-templates you want to have (e.g. login.html, password_change_form.html, ...). It might be a good idea to take a look at the original forms in your django/contrib/admin/templates/registration (or ../admin)-folder to get an idea of what's done in the original templates.
Customize the templates to your needs. If you want to apply the ssame css to every page, I would suggest writing your own base.html and extend it using {% extends "base.html" %}.
Add the views to your urls.py, eg.g.:
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login'),
url(r'^accounts/password_change_done/$', 'django.contrib.auth.views.password_change_done', name="password_change_done"),
url(r'^accounts/password_change/$', 'django.contrib.auth.views.password_change', name='password_change'),
There is no need to define anything in forms.py or views.py.

So make your own form:
From Django-x.x/django/contrib/admin/templates copy base.html, base_site.html and login.html to project_name/templates/admin
Then change the files as necessary.

Related

Django Form Not Rendering HTML from class HomeForm

For some reason I cannot get my Django form to render. I'm not sure what I'm missing.
I'm trying to get the class HomeForm(forms.Form) to render on the myaccount/change.html page and have been unsuccessful.
I'm new to Django so I might be missing a small detail somewhere but I thought I got everything covered from the djago documentation.
If anyone can help me out it would be gladly appreciated. Thanks!
users/forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django import forms
from .models import CustomUser
class HomeForm(forms.Form):
post = forms.CharField()
your_name = forms.CharField(label='Your name', max_length=100)
class CustomUserCreationForm(UserCreationForm):
# job_title = forms.IntegerField(label='2 + 2', label_suffix=' =')
# yes = forms.IntegerField(required=True)
tos_check = forms.BooleanField(required=True, label='I have read and agree to the Terms of Service.')
age_check = forms.BooleanField(required=True, label='I am 21 years of age or older.')
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('username', 'email')
help_texts = {
'username': '',
'email': '',
# 'password1': 'None',
# 'password2': 'Test'
}
class CustomUserChangeForm(UserChangeForm):
tos_checktwo = forms.BooleanField(required=True, label='I have read and agree to the Terms of Service.')
class Meta(UserChangeForm.Meta):
model = CustomUser
fields = ('username', 'email', 'tos_checktwo')
# class Meta:
# model = CustomUser
# fields = ('username', 'email', 'tos_check',)
users/views.py
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.shortcuts import render
from django.template import loader
from django.urls import reverse_lazy
from django.views import generic
from django import forms
from .forms import CustomUserCreationForm
from .forms import HomeForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = HomeForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/home/')
# if a GET (or any other method) we'll create a blank form
else:
form = HomeForm()
return render(request, 'myaccount/change.html', {'form': form})
class SignUp(generic.CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
pages/urls.py
from django.urls import path
from django.urls import path, include
from django.conf.urls import url
from django.conf import settings
from . import views
from .views import HomePageView, MyAccountView, AboutPageView, PrivacyPageView, ContactPageView
urlpatterns = [
path('about/', AboutPageView.as_view(), name='about'),
path('privacy/', PrivacyPageView.as_view(), name='privacy'),
path('contact/', ContactPageView.as_view(), name='contact'),
path('', HomePageView.as_view(), name='home'),
path('myaccount/', MyAccountView.as_view(), name='myaccount'),
url('avatar/', include('avatar.urls')),
url('myaccount/', include('avatar.urls')),
]
templates/myaccount/change.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock content %}
Sir, I don't see any problem in the code shared. But here is 2 hints :
check if in base.html, you have included the block content.
add print(form) before the return in the view to see what you get (the print result will be on the terminal not the browser)
edit :
You should add an url that calls the view :
in url add this line :
path('testform/', view.get_name, name ='get_name')
and then on your brower, test the url 127.0.0.1:8080/testform/
you will need to include {% block content %} and {% endblock %} tags in your base.html file.
When you "extend" the base template, these tags indicate where the extra content should be inserted.
see tte Template Inheritance
#AlouaniYounes Looks like on base.html the my account page was being directed somewhere else. I made the fix to base.html and problem solved. Thanks!

error in database saving

I am trying to create a form and save data to database when the submit button is clicked. But the data is not getting saved to database. i dont get any error. I am django 1.11. I referred to few stackoverflow question and that answers doesnt solve my issue. Could someone help in fixing it? Thanks in advance.
model.py
from __future__ import unicode_literals
from django.db import models
class NameForm(models.Model):
your_name = models.CharField(max_length=200)
views.py
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.views import generic
from django.template.response import TemplateResponse
from home.models import NameForm
from .forms import NameForm
class NameView(generic.View):
model_class = NameForm
initial = {'key': 'value'}
template_name = 'home/name.html'
def get(self, request, *args, **kwargs):
model = self.model_class()
return render(request, self.template_name, {'model': NameForm})
def post(self, request, *args, **kwargs):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('thanks/')
if form.is_valid():
form.save()
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
urls.py
from django.conf.urls import url
from . import views
app_name = 'home'
urlpatterns = [
url(r'^$', views.NameView.as_view(), name='name'),
url(r'^your-name/$', views.NameView.as_view(), name='name'),
url(r'^your-name/thanks/$', views.NameView.as_view(), name='name'),
]
home/name.html
<form action="your-name/" method="post">
{% csrf_token %}
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
forms.py
from .models import NameForm
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
class Meta:
model = NameForm
fields = ['your_name']
You'll get by much easier if you use the batteries included in Django. Here's a list of the fixes in the version below...
Don't reuse names. NameModel is a model, NameForm is a form. (However, you'd usually really elide Model from a model name – it's just that Name sounded like a silly name for a model...)
Use ModelForms when you're managing models. They automatically validate input against your models, let you save the models easily, etc.
Use the CreateView/UpdateView/FormView generic views to deal with model creation, updates, inputs, etc. No code needed, just configuration!
Don't template forms yourself. form.as_p will get you a barebones form; form.your_name would render that field, etc.
Just a fair warning: this is dry-coded, so there might be typos or other small silliness.
models.py
from django.db import models
class NameModel(models.Model):
your_name = models.CharField(max_length=200)
forms.py
from django import forms
class NameForm(forms.ModelForm):
class Meta:
model = NameModel
fields = ['your_name']
views.py
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import NameModel
from .forms import NameForm
class NameView(CreateView):
model_class = NameModel
form_class = NameForm
success_url = reverse_lazy('name-thanks')
initial = {'your_name': 'value'}
template_name = 'home/name.html'
urls.py
from django.conf.urls import url
from django.views.generic import FormView
from .views import NameView
app_name = 'home'
urlpatterns = [
url(r'^$', NameView.as_view(), name='name'),
url(r'^your-name/thanks/$', TemplateView.as_view({'template_name': 'home/thanks.html'}), name='name-thanks'),
]
home/name.html
<form action="your-name/" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="OK">
</form>
That's beacuse you've been redirected (return HttpResponseRedirect('thanks/')) before save
Your version:
if form.is_valid():
return HttpResponseRedirect('thanks/')
if form.is_valid():
form.save()
else:
...
And the version you seek, with redirect only after form saving and removed redundant second form.is_valid() check:
if form.is_valid():
form.save()
return HttpResponseRedirect('thanks/')
else:
...

Django: ModelForm and show data on the same url

I'm new to django and trying to create my first app and I think I might need some little help :)
I have a ModelForm on a site to submit and want to show the data on the same page. I'm having trouble to set up two functions on the same page, I think i might have to use a class and set it in urls.py but I'm not able to make it work :( the code looks like this:
forms.py:
from django import forms
from .models import Eintrag
class NameForm(forms.ModelForm):
class Meta:
model = Eintrag
fields = ['Anmeldung', 'Essen']
urls.py
from django.urls import path
from . import views
app_name = 'form'
urlpatterns = [
path('', views.get_name, name='form'),
]
views.py
from django.shortcuts import render
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import NameForm
from .models import Eintrag
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
eintrag = form.save(commit=False)
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
eintrag.Name = request.user # Set the user object here
eintrag.pub_date = timezone.now() # Set the user object here
eintrag.save()
return render(request, 'form/name.html', {'form': form})
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'form/name.html', {'form': form})
def post_list(request):
posts = Eintrag.objects.all()
return render('form/post_list.html', {'posts': posts})
name.html
...
{% include "form/post_list.html" %}
<form action="/form/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
...
post_list.html
{% for post in posts %}
{{ post }}
{% endfor %}
So the problem is in urls.py only get_name is handled and I'm clueless how I should include post_list. I rather not want to use different url's, do I have to?
Thanks for any help and advice!
You don't need a separate URL or view for the list. Just include the queryset in the context of your get_name view.
posts = Eintrag.objects.all()
return render(request, 'form/name.html', {'form': form, 'posts': posts})
with [Class Based View] it would be better.
But with your view, you can send multiple data via context.
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
''' codes '''
eintrag.save()
return HttpResponseRedirect(request.path) # generate an empty form
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
posts = Eintrag.objects.all() # the queryset is here, and sent via context
return render(request, 'form/name.html', {'form': form,'posts':posts})
I your html remain the same, but keep your form action='' empty
{% include "form/post_list.html" %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>

right username password not login django

I am developing a small website with django and I am using the built-in login view. When I register a standard user and then try to login with the right credentials it shows me the login error "please enter a correct username and password". This problem doesn't occurr with the superusers that I created. The can login with the right credentials without any error message showed.
This is the views.py with my registration view.
from django.shortcuts import redirect, render, get_object_or_404
from django.contrib.auth.models import User
from .forms import UserForm
def register_user(request):
if request.method == "POST":
form = UserForm(request.POST)
if form.is_valid():
user = form.save()
return redirect('user_profile', pk=user.pk)
else:
form = UserForm()
return render(request, 'interport/register_user.html', {'form':form})
The admin.py:
from django.contrib import admin
from django.contrib.auth.models import User
forms.py:
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'username', 'password',)
urls.py:
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
url(r'^accounts/login/$', auth_views.login, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
url(r'^register_user$', views.register_user, name='register_user'),
url(r'^$', views.home, name='home'),
]
the template for login:
{% extends "interport/base.html" %}
{% block content %}
<div class="container">
<div class="row">
<div class="center col s4 offset-s4 card-panel #fff8e1 amber lighten-5">
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
</div>
</div>
</div>
{% endblock %}
You're saving the new user with a plain text password, but Django will always hash the password before checking for validity.
You need to create your users via User.objects.create_user(), which hashes the password correctly, or use user.set_password() to set the hashed password after creating.
The accepted answer is good and old, however I would advice to put those instructions in the save function of the said form.
This way allows you to have a clearer code in your views and an easier maintenance should you change the way the form is handled. you dont have to go back to every function in your views.py where you used that form.
in OP's case, the Form would look like that afterwards:
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'username', 'password',)
def save(self, commit=False):
instance = super(UserForm, self).save(commit=False) # create but don't save yet
if commit:
instance.set_password(instance.password)
instance.save()
return instance
There might be more elegant way, but it's been working for me like that.
to have explanation regarding commit=False : Django ModelForm: What is save(commit=False) used for?

Django Contact Form using ModelForm

I am trying to create a contact form that will both email and store the message. I think I got the model.py, forms.py and admin.py right, and I am able to create and store (not email) a message from the admin. But I am struggling with the view.py that has to both email and store the message.
model.py:
from django.db import models
from django.contrib import admin
class Contact(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
message = models.TextField(max_length=10)
date_created = models.DateField(verbose_name="Created on date", auto_now_add="True")
class ContactAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'message', 'date_created')
forms.py:
from django import forms
from .models import Contact
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
When it comes to the views.py, I need some guidance in order to put together the code for the def contact(request):. I think I will have to include these modules:
from django.conf import settings
from django.shortcuts import render, HttpResponseRedirect, HttpResponse, Http404
from django.core.mail import send_mail
from .forms import ContactForm
from .models import Contact
When it comes to the template part, I am not sure on how to use the template tags to render the contact form in html.
So, I need help to figure out the correct view and template code.. I am of course open to suggestions for the rest of the code as well - As you might guessed, this is my first real Django app.
Thank you!
Something like this:
I would use a django ModelForm to generate the form:
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
exclude = ('date_created', )
Docs: https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#modelform
And FormView for the actual view:
from django.conf import settings
from django.core.mail import send_mail
from django.views.generic import FormView
from .forms import ContactForm
class ContactFormView(FormView):
form_class = ContactForm
template_name = "email_form.html"
success_url = '/email-sent/'
def form_valid(self, form):
message = "{name} / {email} said: ".format(
name=form.cleaned_data.get('name'),
email=form.cleaned_data.get('email'))
message += "\n\n{0}".format(form.cleaned_data.get('message'))
send_mail(
subject=form.cleaned_data.get('subject').strip(),
message=message,
from_email='contact-form#myapp.com',
recipient_list=[settings.LIST_OF_EMAIL_RECIPIENTS],
)
form.save()
return super(ContactFormView, self).form_valid(form)
Docs: https://docs.djangoproject.com/en/1.7/ref/class-based-views/generic-editing/#formview
And your template:
{% extends 'base.html' %}
{% block title %}Send an email{% endblock %}
{% block content %}
<div class="row">
<div class="span6">
<h1>Send an email</h1>
<form action="." method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
{% endblock %}
{% block extrajs %}
<script src="{{ STATIC_URL }}js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(function() {
$('#id_name').focus()
});
</script>
{% endblock %}
Docs: https://docs.djangoproject.com/en/1.7/topics/forms/#the-template

Categories