Django form in an extended template - python

I am very new to Django, I have a home template (home.html) which is extending a base template (base.html) with {% extends "base.html" %}.
base.html containts a contact form.
<form id="email-form" name="email-form" data-name="Email Form" method="post">
{% csrf_token %}
<div>
<label for="Name-2" class="field-label">Full name</label>
{% render_field form.name class+="text-field w-input" %}
</div>
<div>
<label for="Email-2" class="field-label">Email address</label>
{% render_field form.from_email class+="text-field _2 w-input" %}
</div>
<div>
<label for="Phone-2" class="field-label">Phone number</label>
{% render_field form.phone class+="text-field _2 w-input" %}
</div>
<div>
<label for="Timeline" class="field-label">More information</label>
<div>
{% render_field form.message class+="text-field area w-input" %}
</div>
</div>
<div class="algin-center form-actions">
<input type="submit" value="Send Message" data-wait="Please wait..." class="button full w-button">
</div>
</form>
views.py
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(required=True)
from_email = forms.EmailField(required=True)
phone = forms.CharField(required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
def homeView(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
phone = form.cleaned_data['phone']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(name, message, from_email, ['email#email.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
return render(request, "home.html", {'form': form})
The form is rendering fine, however, when I click the submit button nothing happens. I'm guessing this is because the form is not in the homeView directly but through extension, but I have no idea how to fix it, is it possible to have the form in an extended view?

Related

Model form is not able to save in database

I am a beginner in Django
I want to save a form data in database but i am not able to save, followed some tutorials also.
form.py:
from django.forms import ModelForm
from .models import *
class listsForm(ModelForm):
class Meta:
model = todo
fields = "__all__"
views.py:
from django.shortcuts import render
from .models import *
from .form import *
def index(request):
lists = todo.objects.all()
form = listsForm()
context = {
'lists':lists,
'form':form,
}
if request.method == 'POST':
form = listsForm(request.POST)
if form.is_valid:
form.save()
return render(request, 'index.html', context)
models.py:
from django.db import models
class todo(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
created = models.DateField(auto_now_add=True)
def __str__(self):
return self.title
Why are you rendering listsForm?
Your form should be in the template not rendered!
In index.html, your form should looks like the following:
<form action="{% url 'create_todo' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" id="title" required></div>
<div class="form-group">
<label for="Description">Description</label>
<textarea name="description" class="form-control" id="description" ></textarea></div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
In views.py
def index(request):
return render(request, 'index.html')
def create_todo(request):
if request.method == 'POST':
form = listsForm(request.POST)
if form.is_valid():
form.save()
return redirect('index')
In urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('create_todo/', views.create_todo, name='create_todo')
]
You will still need to render existed todos, preferably in another template.
So in views.py
def alltodos(request):
todos = Todo.objects.all()
return render(request, 'index.html', {'todos':todos})
In index.html, above form or after it, it doesn't matter, just for clear visibility
<div class="row justify-content-center mt-5">
<div class="col-md-10">
{% if todos %}
<div class="list-group">
{% for todo in todos %}
<a class="list-group-item list-group-item-action><b>{{ todo.title }}</b>{{ todo.description|truncatechars:30 }}{% endif %}</a>
{% endfor %}
</div>
{% else %}
<div class="text-center">
<h2>Looks like you don't have any todos!</h2>
<br>
</div>
{% endif %}
</div>
</div>
In urls.py add
path('todos', views.alltodos, name='alltodos'),
Advanced project of mine
I have find out why it was not working,
I was using <input type="button"> for submit button
but when I changed it to <button type="submit"> it works.

How to you put a checkbox in a django.contrib.auth.forms UserCreationForm

I have multiple fields in my Django UserCreationForm including the already included username, password 1, and password 2. I have also added and email field. I am unable to add a checkbox.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
I want there to be a checkbox to declare if the user wants to register as a teacher or as a student.
{% extends 'base.html' %}
{% block content %}
<div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
</form>
</div>
{% endblock %}
from django.shortcuts import render, redirect
from .forms import UserRegisterForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('/')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
return render(request, 'users/profile.html')
You already added the BooleanField in django form here:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
looks good you only need to add the it to your html
{% extends 'base.html' %}
{% block content %} <div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
<div name="new is teacher checkbox">
{{form.is_teacher}}
</div>
</form>
</div> {% endblock %}
You can access the value of is_teacher in views too by forms.cleaned_data.get('is_teacher')

Django creation of new user failed

I'm facing some difficulties while trying to create a new user using UserCreationForm in Django.
I think that the issue is on the signup HTML page, but I can't really understand what am I doing wrong.
When I click submit after filling the required fields nothing happens.
I hope you could help me out.
Part of signup.html:
<div class="container">
<form id="register-form" method="post">
{% csrf_token %}
{% for field in form %}
{% if field.name == 'first_name' %}
<div class="form-group">
<input id="register-first_name" type="text" name="registerFirst" required
class="input-material">
<label for="register-first_name" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'last_name' %}
<div class="form-group">
<input id="register-last_name" type="text" name="registerLast" required
class="input-material">
<label for="register-last_name" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'username' %}
<div class="form-group">
<input id="username" type="text" name="username" required
class="input-material">
<label for="username" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'email' %}
<div class="form-group">
<input id="register-email" type="text" name="registerEmail" required
class="input-material">
<label for="register-email" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'password' %}
<div class="form-group">
<input id={{ form.name.name }} type="text" name="password" required
class="input-material">
<label for={{ form.name.name }} class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% endfor %}
<input id="register" type="submit" value="Register" class="btn btn-primary">
</form>
<div/>
my forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password', )
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
my views.py:
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth import authenticate
from django.contrib.auth import login as login_a
from django.shortcuts import render, redirect
from movie.forms import SignUpForm
def index(request):
return render(request, 'home.html')
def login(request):
return render(request,'login.html')
def logout(request):
return render(request,'logout.html')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password')
print (username);
print (raw_password);
user = authenticate(username=username, password=raw_password)
login_a(request, user)
return redirect('login')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
Your form looks incorrect. You are using incorrect values for the names (e.g. name="registerFirst" instead of name="first_name"), so the Django form will not use the submitted values. Then you are not displaying the field errors, so you don't get any useful feedback when you submit the form.
I would start by letting Django render the form. That will let you fix any problems in the view.
<form id="register-form" method="post">
{% csrf_token %}
{{ form.as_p }}
<input id="register" type="submit" value="Register" class="btn btn-primary">
</form>
To help debugging, you can print values in your view, for example add print(form.errors) after the if form.is_valid(): block.
Then, once the view is working with the simple template, you can render the fields manually if you need more control over the layout. See the docs on rendering fields manually for more info. If you do this, remember to display any field/form errors to the user.
If you do render the fields manually, you can access the fields with {{ form.first_name }}, instead of looping through {% for field in form %} then having to check field.name.

how to put a login form using django

After hours and hours of trying, i still cannot seem to make it happen.
basically Im trying to put a login form inside this .post_list.html using django along with the postform. (so there are 2 forms)
this is the views.py
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth import login
from django.http import HttpResponseRedirect
from django.template.response import TemplateResponse
from django.contrib.auth.decorators import login_required
from .forms import PostForm, AuthenticationForm
from .models import Post
def post_detail(request, id=None):
# instance = Post.objects.get(id=1)
instance = get_object_or_404(Post, id=id)
context = {
"title": instance.title,
"instance": instance,
}
return render(request, "post_detail.html", context)
def post_list(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
login(request, form.get_user())
return HttpResponseRedirect('/post-list/')
else:
form = AuthenticationForm(request)
return TemplateResponse(request, 'login.html', {'form': form})
else:
form = AuthenticationForm()
postform = PostForm(request.POST or None)
if postform.is_valid():
instance = postform.save(commit=False)
print (postform.cleaned_data.get("title"))
instance.save()
# message success
messages.success(request, "Successfully Created")
return HttpResponseRedirect(instance.get())
# else:
#messages.error(request, "Not Successfully Created")
queryset = Post.objects.all()#.order_by("-timestamp")
context = {
"object_list": queryset,
"title": "List",
"form": postform,
"form2": form
}
return render(request, "post_list.html", context)
and this is the forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content"
]
from django.contrib.auth import authenticate
class AuthenticationForm(forms.Form):
username = forms.CharField(max_length=254)
password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
username = self.cleaned_data['username']
password = self.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is None:
raise forms.ValidationError('invalid_login')
return self.cleaned_data
and post_lost.html
{% extends "base.html" %}
{% block content %}
<form method="post" action="">
{% csrf_token %}
Username: {{ form.username }} {{ form.username.errors }}<br>
Password: {{ form.password }} {{ form.password.errors }}<br>
{{ form.errors }}<br>
<input type="submit" value="login" />
</form>
<div class='two columns right mgr'>
<h1>Form</h1>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<input class="button-primary" type='submit' value='Create Post' />
</form>
</div>
<div class='four columns left'>
<h1>{{ title }}</h1>
{% for obj in object_list %}
<div class="row">
<div>
<a href='{{ obj.get_absolute_url }}'>
<div class="thumbnail">
<!--<img src="..." alt="...">!-->
<div class="caption">
<h3>{{ obj.title }}<small> {{ obj.timestamp|timesince }} ago</small></h3>
<p>{{ obj.content|linebreaks|truncatechars:120 }}</p>
<!-- <p>View </p>-->
</div>
</div></a>
</div>
<hr />
</div>
{% endfor %}
</div>
{% endblock content %}
could you please help me out? thanks.
My guess is you got this issue because of naming.
You passing into context the following things:
form = AuthenticationForm()
postform = PostForm(request.POST or None)
...
context = {
"object_list": queryset,
"title": "List",
"form": postform,
"form2": form
}
So, when you try to access form.username you fail, because in the template form is a postform. And postform has no 'usarname' field.
So look like you should try this:
<form method="post" action="">
{% csrf_token %}
Username: {{ form2.username }} {{ form2.username.errors }}<br>
Password: {{ form2.password }} {{ form2.password.errors }}<br>
{{ form2.errors }}<br>
<input type="submit" value="login" />
</form>

Cannot see the form input field at all

I would like to collect the content that user input, then change the database using POST method. But i just blank when i clicked post button on the website.
Here's the views.py
class PostTweet(View):
def post(self, request, username):
form = TweetForm(request.POST)
print form.is_valid()
print request.POST
print form.errors
if form.is_valid():
user = User.objects.get(username=username)
tweet = Tweet(text=form.cleaned_data['text'],
user=user,
country=form.cleaned_data['country'])
tweet.save()
return HttpResponseRedirect('/user/'+username)
else:
form = TweetForm()
return render(request, 'profile.html', {'form':form})
class Profile(View):
"""
User Profile page reachable from /user/<username> URL
"""
def get(self, request, username):
params = {}
user = User.objects.get(username = username)
tweets = Tweet.objects.filter(user=user)
params["tweets"] = tweets
params["user"] = user
return render(request, 'profile.html', params)
forms.py
from django import forms
class TweetForm(forms.Form):
text = forms.CharField(widget=forms.Textarea, max_length=160)
country = forms.CharField(widget=forms.HiddenInput(),required=False)
profile.html
{% extends "base.html" %}
{% block content %}
<div class="row clearfix">
<div class="col-md-6 col-md-offset-3 column">
<form id="form" method="POST" action="post/">{% csrf_token %}
<div class="col-md-8 fieldWrapper">
{{ form }}
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Post</button>
</span>
</div>
</form>
</div>
<h3> </h3>
<div class="col-md-12 column">
{% for tweet in tweets %}
<div class="well">
<span>{{ tweet.text}}</span>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
Here's the urls.py
from django.conf.urls import include, url, patterns
from django.contrib import admin
from tweets.views import Index, Profile, PostTweet, HashTagCloud
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', Index.as_view()),
url(r'^user/(\w+)/$', Profile.as_view()),
url(r'^admin/', include(admin.site.urls)),
url(r'^user/(\w+)/post/$', PostTweet.as_view()),
url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
)
Anyone just give me a hint would be appreciated :-)
Adding {{form}} only should not render the field. form is an object with fields as properties. In your html try substituting {{form}} with {{form.text}}
Also you can try passing the object "form" as follows:
return render(request, 'profile.html', form = form)

Categories