Have been trying to use Django forms for contact tab - but getting the - Error ! Please! Make sure all fields are entered and valid.
**forms.py **
from django import forms
from content.models import Contact
class ContactForm(forms.ModelForm):
fullname = forms.CharField(required=True,max_length=100)
email = forms.EmailField(required=True,max_length=100)
subject = forms.CharField(required=True,max_length=300)
phone_number = forms.CharField(required=True,max_length=100)
message = forms.CharField(required=True,widget=forms.Textarea)
class Meta:
model = Contact
fields = [
'fullname',
'email',
'subject',
'message',
'phone_number',
]
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['fullname'].widget.attrs['placeholder'] = 'Your FullName'
self.fields['fullname'].widget.attrs['class'] = 'form-control form-control-lg'
self.fields['email'].widget.attrs['placeholder'] = 'Your Email'
self.fields['email'].widget.attrs['class'] = 'form-control form-control-sm'
self.fields['subject'].widget.attrs['placeholder'] = 'Subject'
self.fields['subject'].widget.attrs['class'] = 'form-control form-control-sm'
self.fields['phone_number'].widget.attrs['placeholder'] = 'Your Phone Number'
self.fields['phone_number'].widget.attrs['class'] = 'form-control'
self.fields['message'].widget.attrs['placeholder'] = 'Your Message'
self.fields['message'].widget.attrs['cols'] = '30'
self.fields['message'].widget.attrs['rows'] = '10'
views.py
from email.message import EmailMessage
from django.shortcuts import render
from content.forms import ContactForm
from content.models import About, Profile,Primaryskill,Secondaryskill,Services,Portfolio,Blog,Testimonial,Contact
from django.contrib import messages
#for sending emails and contact
from django.http import HttpResponseRedirect
from django.core.mail import send_mail
from django.conf import settings
from django.template.loader import render_to_string
from django.template import loader
# Create your views here.
def Homepage(request):
#django orm concept
profile = Profile.objects.first() #this will fetch all the data from Profile table first row and store it in profile
about = About.objects.first()
primaryskill = Primaryskill.objects.all()
secondaryskill = Secondaryskill.objects.all()
services = Services.objects.all()
testimonials = Testimonial.objects.all()
form = ContactForm()
context = {
'profile':profile,
'about': about,
'primaryskill':primaryskill,
'secondaryskill':secondaryskill,
'services':services,
'testimonials':testimonials,
'form':form,
}
return render(request,"index.html",context)
def MailContact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
data = Contact()
data.fullname = form.cleaned_data['fullname']
data.email = form.cleaned_data['email']
data.subject = form.cleaned_data['subject']
data.phone_number = form.cleaned_data['phone_number']
data.message = form.cleaned_data['message']
data.save()
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
fullname = form.cleaned_data['fullname']
phone_number = form.cleaned_data['phone_number']
email = form.cleaned_data['email']
email_from = settings.EMAIL_HOST_USER
recipient_list = ['abc#gmail.com',]
html_message = loader.render_to_string(
'email.html',
{
'subject':subject,
'message':message,
'fullname':fullname,
'email':email,
'phone_number':phone_number,
}
)
if subject and message and email_from and recipient_list and html_message:
try:
send_mail(subject, message, email_from, recipient_list, html_message = html_message, fail_silently=False)
except:
messages.error(request,"Cannot send mail right now, Try again later")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
messages.success(request,"Message sent successfully")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
messages.error(request,"Please! Make sure all fields are entered and valid.")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
messages.error(request,"Please! Make sure all fields are entered and valid.")
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
contact.html
<div data-aos="fade-left" data-aos-duration="500" data-aos-delay="200" data-aos-once="true" class="rn-contact-area section-height">
<div class="inner">
<h5 class="title">
Contact With Me
</h5>
{% if messages %}
{% for message in messages %}
<div id="index-alert"
class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %} alert-dismissible bg-{% if message.tags == 'success' %}success{% elif message.tags == 'danger' %}danger{% elif message.tags == 'primary' %}primary{% endif %}">
×
<strong class="text-white"> {% if message.tags == 'success' %}Success{% elif message.tags == 'danger' %} Error {% elif message.tags == 'primary' %}Message{% endif %} ! </strong><span class="text-white">{{message}}</span>
</div>
{% endfor %}
{% endif %}
<!--
<script>
window.setTimeout(function () {
$("#index-alert").fadeTo(800, 0).slideUp(800, function () {
$(this).remove();
});
}, 2000);
</script>
-->
<!-- Form area Srart -->
<form action = "{% url 'Contact' %}" method = "POST">
{% csrf_token %}
<div class="contact-form-wrapper">
<div class="introduce">
<div class="row">
<div class="col-lg-12 col-xl-6">
<div class="form-group">
<label for="name">Your Name</label>
{{form.fullname}}
</div>
</div>
<div class="col-lg-12 col-xl-6">
<div class="form-group">
<label for="phone">Phone Number</label>
{{form.phone_number}}
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label for="email">Email</label>
{{form.email}}
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label for="subject">subject</label>
{{form.subject}}
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label for="message">Your Message</label>
{{form.message}}
</div>
</div>
<div class="col-lg-12">
<button class="rn-btn" type="submit">
<span>SEND MESSAGE</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</button>
</div>
</div>
</div>
</div></form?
<! --Form area End -->
</div>
</div>
email.html
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Email</title>
</head>
<body>
<h1>Hi - this is contact form message</h1>
<p>
{{fullname}}
{{phone_number}}
{{email}}
{{subject}}
{{message}}
</p>
</body>
</html>
The HTML code is displaying so - I think it's working fine and I tried several different values again and again but it is not validating.
Thank you so much for helping!!
Related
This will be a lengthy post, please have patience with me, I just started with Django and try to wrap my head around it.
I created a site that will go thru exam questions one at a time, displaying the question and the multiple choice answers like on countless other websites.
The challenge I experience is when the user clicks "NEXT" on the pagination buttons, I would like for the selected answer(option) to be saved back to the database.
I tried it with AJAX scripts but the view never got executed.
Maybe there is a better way to do this or could you please point me into the right direction? I will post all of my code and hope someone can please assist me.
Thank you for taking the time to look at this.
I start with the models.py:
from django.db import models
class QuesModel(models.Model):
question = models.TextField(null=True)
code_snippet = models.TextField(null=True)
op1 = models.CharField(max_length=200,null=True)
op2 = models.CharField(max_length=200,null=True)
op3 = models.CharField(max_length=200,null=True)
op4 = models.CharField(max_length=200,null=True)
ans = models.CharField(max_length=200,null=True)
def __str__(self):
return self.question
class Answer(models.Model):
ans_id = models.AutoField(primary_key=True)
question_id = models.ForeignKey(QuesModel, on_delete=models.CASCADE)
fname = models.CharField(max_length=50)
lname = models.CharField(max_length=50)
examdate = models.DateField(auto_now_add =True)
answer = models.PositiveSmallIntegerField()
def __int__(self):
return QuesModel.question[self.question_id]
template is home.html:
{% extends 'Quiz/dependencies.html' %}
{% block content %}
{% load static %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="container">
<h1>Welcome to my Quiz</h1>
{% for q in page_obj %}
<form method="post" action="{% url 'submit_answers' %}">
{% csrf_token %}
<input type="hidden" name="question_id" value="{{ q.id }}">
<!-- <input type="hidden" name="answer" value="{{ answer }}"> -->
<input type="hidden" name="date" value="{{ default_date }}">
<div class="form-group">
<div class="card text-bg-light mb-0" style="max-width: 50rem;">
<div class="card-header">
<code>
Question {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}<br>
{{q.question}}
</code>
</div>
<div class="card-body">
<class="card-text">
<label for="question">
<pre class="python"><code>{{q.code_snippet|linebreaks|escape}}</code></pre>
</label>
</div>
</div>
<br>
<div class="form-check">
<input class="form-check-input" type="radio" name="{{ q.question }}" id="option1" value="1" data-question-id="{{ q.id }} required>
<label class="form-check-label" for="option1">
{{ q.op1 }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="{{ q.question }}" id="option2" value="2" data-question-id="{{ q.id }} required>
<label class="form-check-label" for="option2">
{{ q.op2 }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios1" data-question-id="{{ q.id }} value="3">
<label class="form-check-label" for="gridRadios1">
{{q.op3}}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="{{q.question}}" id="gridRadios2" data-question-id="{{ q.id }} value="4">
<label class="form-check-label" for="gridRadios2">
{{q.op4}}
</label>
</div>
<br>
</div>
</div>
</div>
</div>
{% endfor %}
<div class="container">
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% endif %}
<li class="page-item disabled">
<a class="page-link" tabindex="-1" aria-disabled="true">Question {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</a>
</li>
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="{% url 'home' %}?page={{ page_obj.next_page_number }}" >Next</a>
</li>
{% endif %}
</ul>
</nav>
</div>
<div class="container">
<input id='timer' type='hidden' name="timer" value="">
<br>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
{% block script %}
<script>
const timer=document.getElementById('displaytimer')
console.log(timer.textContent)
const inputtag = document.getElementById('timer')
t=0
setInterval(()=>{
t+=1
timer.innerHTML ="<b>Timer: " +t+" seconds</b>"
inputtag.value = t
},1000)
</script>
{% endblock script %}
</div>
{% endblock %}
Last is the views.py:
from django.shortcuts import redirect,render
from django.contrib.auth import login,logout,authenticate
from .forms import *
from .models import *
from django.http import HttpResponse
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
import datetime
def home(request):
print("HOMEVIEW")
print("REQUEST METHOD=" + request.method) # Debugging line
print("POST=")
print(request.POST) # Debugging line
# Render the question page
if request.method == 'POST':
print("IN POST")
questions=QuesModel.objects.all()
paginator = Paginator(questions, 1)
page_number = request.GET.get('page')
try:
page_obj = paginator.page(page_number)
except PageNotAnInteger:
# If the page is not an integer, show the first page of results
page_obj = paginator.page(1)
except EmptyPage:
# If the page is out of range, show the last page of results
page_obj = paginator.page(paginator.num_pages)
context = {
'page_obj': page_obj,
'answer': request.POST.get('answer'), # define and pass answer to template
}
return render(request,'Quiz/home.html',context)
def save_answer(request):
print("XXXXXXX")
print(request.method) # Debugging line
print(request.POST) # Debugging line
if request.method == 'POST':
# answer = request.POST['answer']
# question_id = request.POST['question_id']
# # Save the answer to the database
# answer = Answer(question_id=question_id, examdate=default_date, answer=answer)
# answer.save()
return HttpResponse('Success')
#Return an error response if the request method is not 'POST'
return HttpResponse('Error: Invalid request method')
def submit_answers(request):
print("submit_answers")
if request.method == 'POST':
print(request.POST)
questions=QuesModel.objects.all()
score=0
wrong=0
correct=0
total=0
incorrect_answers = []
for q in questions:
items = {'op1': q.op1, 'op2': q.op2, 'op3': q.op3, 'op4': q.op4}
total+=1
answer = request.POST.get(q.question) # Gets user’s choice, i.e the key of answer
print(request.POST.get(q.question))
print(q.ans)
print()
if q.ans == request.POST.get(q.question):
score+=10
correct+=1
else:
if q.ans != request.POST.get(q.question):
wrong += 1
testvar=request.POST.get(q.question)
incorrect_answers.append({'question': q.question, 'correct_answer': q.ans, 'user_answer': request.POST.get(q.question) } )
percent = score/(total*10) *100
context = {
'score':score,
'time': request.POST.get('timer'),
'correct':correct,
'wrong':wrong,
'percent':percent,
'total':total,
'incorrect_answers': incorrect_answers, # pass list to template
}
return render(request,'Quiz/result.html',context)
def default_date():
return datetime.datetime.now()
def pageme(request):
print("pageme_here")
questions = QuesModel.objects.all()
paginator = Paginator(questions, 1)
page_number = request.GET.get('page')
try:
page_obj = paginator.page(page_number)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
context = {
'page_obj': page_obj,
}
return render(request, 'Quiz/pageme.html', context)
def saveme(request):
# Perform some actions here, such as saving data to the database
print("saveme_here") # Debug statement
return HttpResponse("Save successful") # Return a response to the client
# def save_answer(request):
# if request.method == 'POST':
# answer = request.POST['answer']
# question_id = request.POST['question_id']
# # Save the answer to the database
# answer = Answer(question_id=question_id, examdate=default_date, answer=answer)
# answer.save()
# return HttpResponse('Success')
# return HttpResponse('Error')
# def home(request):
# if request.method == 'POST':
# print(request.POST)
# questions=QuesModel.objects.all()
# #answer
# answer = request.POST.get('answer')
# question_id = request.POST.get('question_id')
# examdate = request.POST.get('date')
# answer = Answer(question_id=question_id, examdate=examdate, answer=answer)
# answer.save()
# #end answer
# score=0
# wrong=0
# correct=0
# total=0
# incorrect_answers = []
# for q in questions:
# items = {'op1': q.op1, 'op2': q.op2, 'op3': q.op3, 'op4': q.op4}
# total+=1
# answer = request.POST.get(q.question) # Gets user’s choice, i.e the key of answer
# print(request.POST.get(q.question))
# print(q.ans)
# print()
# if q.ans == request.POST.get(q.question):
# score+=10
# correct+=1
# else:
# if q.ans != request.POST.get(q.question):
# wrong += 1
# testvar=request.POST.get(q.question)
# incorrect_answers.append({'question': q.question, 'correct_answer': q.ans, 'user_answer': request.POST.get(q.question) } )
# percent = score/(total*10) *100
# context = {
# 'score':score,
# 'time': request.POST.get('timer'),
# 'correct':correct,
# 'wrong':wrong,
# 'percent':percent,
# 'total':total,
# 'incorrect_answers': incorrect_answers, # pass list to template
# }
# return render(request,'Quiz/result.html',context)
# else:
# questions=QuesModel.objects.all()
# paginator = Paginator(questions, 1)
# page_number = request.GET.get('page')
# try:
# page_obj = paginator.page(page_number)
# except PageNotAnInteger:
# page_obj = paginator.page(1)
# except EmptyPage:
# page_obj = paginator.page(paginator.num_pages)
# context = {
# 'page_obj': page_obj,
# }
# return render(request,'Quiz/home.html',context)
def addQuestion(request):
if request.user.is_staff:
form=addQuestionform()
if(request.method=='POST'):
form=addQuestionform(request.POST)
if(form.is_valid()):
form.save()
return redirect('/')
context={'form':form}
return render(request,'Quiz/addQuestion.html',context)
else:
return redirect('home')
def registerPage(request):
if request.user.is_authenticated:
return redirect('home')
else:
form = createuserform()
if request.method=='POST':
form = createuserform(request.POST)
if form.is_valid() :
user=form.save()
return redirect('login')
context={
'form':form,
}
return render(request,'Quiz/register.html',context)
def loginPage(request):
if request.user.is_authenticated:
return redirect('home')
else:
if request.method=="POST":
username=request.POST.get('username')
password=request.POST.get('password')
user=authenticate(request,username=username,password=password)
if user is not None:
login(request,user)
return redirect('/')
context={}
return render(request,'Quiz/login.html',context)
def logoutPage(request):
logout(request)
return redirect('/')
Please excuse this messy code, I tried all kinds of things and now I hope I can finish it with your help.
Here, I have tried to change your code and made some changes.
models.py
from django.db import models
class QuesModel(models.Model):
question = models.TextField(null=True)
code_snippet = models.TextField(null=True)
op1 = models.CharField(max_length=200,null=True)
op2 = models.CharField(max_length=200,null=True)
op3 = models.CharField(max_length=200,null=True)
op4 = models.CharField(max_length=200,null=True)
ans = models.CharField(max_length=200,null=True)
def __str__(self):
return self.question
class Answer(models.Model):
ques = models.ForeignKey(QuesModel, on_delete=models.CASCADE)
fname = models.CharField(max_length=50)
lname = models.CharField(max_length=50)
examdate = models.DateField(auto_now_add =True)
answer = models.CharField(max_length=200,null=True)
def __int__(self):
return self.ques__question
Note: Django provides a default "id" field for each model so no need for ans_id and in the Answer model 'question' field is updated with alias 'ques'
Then go to your command line and execute commands
python manage.py makemigrations
python manage.py migrate
Add some questions and answers
views.py
from django.contrib.auth import login,logout,authenticate
from .forms import *
from .models import *
from django.http import HttpResponse, JsonResponse
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
import datetime
import json
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render, redirect
# here Disabling CSRF protection for this view function
#csrf_exempt
def home(request):
if request.method == "GET":
questions=QuesModel.objects.all()
paginator = Paginator(questions, 1)
page_number = request.GET.get('page')
try:
page_obj = paginator.get_page(page_number)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
context = {
'page_obj': page_obj,
'default_date': default_date
}
return render(request,'Quiz/home.html',context)
# Render the question page
if request.method == 'POST':
parse_json = json.loads(request.body)
for k,v in parse_json.items():
ques = QuesModel.objects.get(id=int(k))
answer = v
obj, created = Answer.objects.update_or_create(
ques=ques, answer=answer,
defaults={'answer': answer, 'examdate': default_date, 'fname': "Bhavesh", "lname": "Patil"})
return redirect('get-results')
# GET Result Page
def get_result(request):
score=0
wrong=0
correct=0
total= (QuesModel.objects.all().count()) * 10
# Note you have to map user here I am keeping user static with fname -> Bhavesh and lname -> Patil ... Its me
get_answers = Answer.objects.filter(fname='Bhavesh', lname='Patil')
for i in get_answers:
if i.answer == i.ques.ans:
score += 10
correct += 1
else:
wrong += 1
percentage = score/total*100
context = {'percent': round(percentage,2), 'correct':correct, 'wrong': wrong, 'total':total, 'score': score}
return render(request, 'Quiz/results.html', context)
def default_date():
return datetime.datetime.now()
def addQuestion(request):
if request.user.is_staff:
form=addQuestionform()
if request.method=='POST':
form=addQuestionform(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context={'form':form}
return render(request,'Quiz/addQuestion.html',context)
else:
return redirect('home')
def registerPage(request):
if request.user.is_authenticated:
return redirect('home')
else:
form = createuserform()
if request.method=='POST':
form = createuserform(request.POST)
if form.is_valid() :
user=form.save()
return redirect('login')
context={
'form':form,
}
return render(request,'Quiz/register.html',context)
def loginPage(request):
if request.user.is_authenticated:
return redirect('home')
else:
if request.method=="POST":
username=request.POST.get('username')
password=request.POST.get('password')
user=authenticate(request,username=username,password=password)
if user is not None:
login(request,user)
return redirect('/')
context={}
return render(request,'Quiz/login.html',context)
def logoutPage(request):
logout(request)
return redirect('/')
Note: Be careful while copying the code ... it may give Indentation error so check that as well
Now just replace your home template with this home.html
(here, I didn't have any idea of 'dependencies.html' so I haven't extended that so I have created home.html and results.html )
add below two templates in folder "Quiz". Quiz will have this templates
Quiz |--- home.html
|--- results.html
|--- dependencies.html
|--- ...
home.html
{% comment %}<!-- {% extends 'Quiz/dependencies.html' %} --> {% endcomment %}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
{% block content %}
{% load static %}
<div class="container">
<h1>Welcome to my Quiz</h1>
{% for q in page_obj %}
<form>
<input type="hidden" name="question_id" value="{{ q.id }}" id="questionID">
<!-- <input type="hidden" name="answer" value="{{ answer }}"> -->
<input type="hidden" name="date" value="{{ default_date }}">
<div class="form-group">
<div class="card text-bg-light mb-0" style="max-width: 50rem;">
<div class="card-header">
<code>
Question {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}<br>
{{q.question}}
</code>
</div>
<div class="card-body">
<class="card-text">
<label for="question">
<pre class="python"><code>{{q.code_snippet|linebreaks|escape}}</code></pre>
</label>
</div>
</div>
<br>
<div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question" id="option1" value="{{ q.op1 }}" data-question-id="{{ q.id }}" onchange="submitValue(this)">
<label class="form-check-label" for="option1">
{{ q.op1 }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question" id="option2" value="{{ q.op2 }}"" data-question-id="{{ q.id }}" onchange="submitValue(this)">
<label class="form-check-label" for="option2" >
{{ q.op2 }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question" id="option3" data-question-id="{{ q.id }}" value="{{ q.op3 }}" onchange="submitValue(this)">
<label class="form-check-label" for="option3" >
{{q.op3}}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question" id="option4" data-question-id="{{ q.id }}" value="{{ q.op4 }}" onchange="submitValue(this)">
<label class="form-check-label" for="option4">
{{q.op4}}
</label>
</div>
</div>
<br>
</div>
</div>
</div>
</div>
{% endfor %}
<div class="container">
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% endif %}
<li class="page-item disabled">
<a class="page-link" tabindex="-1" aria-disabled="true">Question {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</a>
</li>
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="{% url 'home' %}?page={{ page_obj.next_page_number }}" >Next</a>
</li>
{% endif %}
</ul>
</nav>
</div>
<div class="container">
<input id='timer' type='hidden' name="timer" value="">
<br>
<button type="submit" onclick="submitResult()" class="btn btn-primary">Submit</button>
</div>
</form>
{% block script %}
<script>
const timer=document.getElementById('displaytimer')
console.log(timer.textContent)
const inputtag = document.getElementById('timer')
t=0
setInterval(()=>{
t+=1
timer.innerHTML ="<b>Timer: " +t+" seconds</b>"
inputtag.value = t
},1000)
</script>
{% endblock script %}
</div>
{% endblock %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script>
// this function will store user choose answer in session storage
// you can see this storage -> just google it "how to see session storage in browser?"
function submitValue(ele){
var questionID = document.getElementById('questionID').value
var answer = ele.value
sessionStorage.setItem(questionID, answer);
}
</script>
<script>
// this script will keep track of user activity i.e retrive user answers from session storage. ie if you move to previous or next page user's choosed answers will be displayed.
$(window).on('load', function(){
console.log(sessionStorage)
var questionID = document.getElementById('questionID').value
var arrayElements = document.getElementsByClassName('form-check-input')
if (sessionStorage.length){
var value = sessionStorage.getItem(questionID)
// console.log(arrayElements)
const ele = Array.prototype.filter.call(arrayElements, (ele) => ele.value == value)
console.log(ele)
if (ele.length > 0){
ele[0].checked = true;
}
}
});
</script>
<script>
// this function will send user result to server and redirect to result page
function submitResult(){
fetch("{% url 'home' %}", {
method: "POST",
body: JSON.stringify(sessionStorage),
headers: {
"Content-type": "text/html; charset=UTF-8"
}
}).then((response) => {
window.location.replace("{% url 'get-results' %}");
sessionStorage.clear();
});
}
</script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
Next step, Add results.html to quiz
results.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Results</title>
</head>
<body>
<div class="m-4">
<table class="table table-bordered">
<thead>
<tr>
<th colspan="2">Result</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Wrong Answers</th>
<td>{{wrong}}</td>
</tr>
<tr>
<th scope="row">Correct Answers</th>
<td>{{correct}}</td>
</tr>
<tr>
<th scope="row">Total Score</th>
<td>{{score}} / <span><b>{{total}}</b></span></td>
</tr>
<tr>
<th scope="row">Percentage</th>
<td>{{percent}} %</td>
</tr>
</tbody>
</table>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
Note: : Here you can customize above template...I kept it simple and focused on your problem statement
Final step is route urls,
urls.py
from django.contrib import admin
from django.urls import path
from .views import *
urlpatterns = [
path('admin/', admin.site.urls),
path('', home, name='home'),
path('get-result/', get_result, name='get-results'),
# ... your url routes
]
This all took my day so please verify and let me know whether this solves your problem or not...
Thank You
I am struggling passing data to a form using pytest. I wish to pass the username and password to a login form. Here is what I have tried:
conftest.py
import pytest
from wahoo_connect import init_app, db
from wahoo_connect.models import User
from dotenv import load_dotenv
load_dotenv('.flaskenv')
#pytest.fixture(scope='module')
def app():
app = init_app()
with app.app_context():
db.create_all()
user = User(username='testuser', email='test#gmail.com', forename='Test', surname='User', confirmed=True)
user.set_password('testing')
db.session.add(user)
db.session.commit()
yield app
#pytest.fixture(scope='module')
def client(app):
return app.test_client()
this sets up a client fixture which is used by my test:
def test_index_page__logged_in(client):
with client:
formdata = {'username': 'testuser', 'password': 'testing', 'remember_me': False}
client.post('/auth/login', data=formdata)
assert current_user.username == 'testuser'
the route is defined in a blueprint as:
#auth_bp.route('/login', methods=['GET', 'POST'])
def login():
# Login route logic goes here
if current_user.is_authenticated:
return redirect(url_for('home_bp.index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password', 'warning')
return redirect(url_for('auth_bp.login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('home_bp.index')
return redirect(next_page)
return render_template('auth/login.html', title='Sign In', form=form)
and here is the form:
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
and the template:
{% extends "base.html" %}
{% block content %}
<div class="form-signin text-center">
<form action="" method="post" novalidate>
<h3>Please sign in</h3>
<div class="form-floating">
{{ form.username(type="text", class="form-control", id="floatingInput", placeholder="Username") }}
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
<label for="floatingInput">{{ form.username.label.text }}</label>
</div>
<div class="form-floating">
{{ form.password(type="password", class="form-control", id="floatingPassword", placeholder="Password") }}
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
<label for="floatingPassword">{{ form.password.label.text }}</label>
</div>
<div class="checkbox mb-3">
<label>
{{ form.remember_me() }} {{ form.remember_me.label.text }}
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">{{ form.submit.label.text }}</button>
{{ form.hidden_tag() }}
</form>
</div>
<p class="text-center">Forgot Your Password? Click to Reset</p>
<p class="text-center pt-3">Create an Account</p>
{% endblock %}
I can see the data before the "if form.validate_on_submit():" statement in the view and it is correct, but I can never get beyond this point in the submission process. I seem to be missing something!
Thank you
Martyn
It seems that I was missing an important flag:
WTF_CSRF_ENABLED = False
it now works!
I have a situation where I want to have published functionality for articles, and I have it. The problem is that I can't get my unit test to work properly, trying to post True to the published field.
Here's what my tests look like.
class ArticleDetailViewTest(TestCase):
def setUp(self):
email = 'testuser#gmail.com'
first_name = 'test'
last_name = 'user'
password = 'test15146'
user = User.objects.create_user(email, first_name, last_name, password)
self.client = Client()
self.client.login(username='testuser#gmail.com', password='test15146')
def test_can_publish_article_from_POST(self):
other_article_two = Article.objects.create(name='Test Name One', author=User.objects.get(email='testuser#gmail.com'))
correct_article_two = Article.objects.create(name='Test Name Two', author=User.objects.get(email='testuser#gmail.com'))
response = self.client.post(reverse('publish_article', kwargs={'pk' : correct_article_two.pk}))
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, f'/articles/{correct_article_two.pk}/')
self.assertEqual(correct_article_two.published, True)
Here's what my publish article view looks like.
def publish_article(request, pk):
article = get_object_or_404(models.Article, pk=pk)
if request.method == "POST":
article.published = True
article.save(update_fields=['published'])
return redirect('article_detail_view', pk=article.pk)
else:
raise Http404
Here are my urls.
from django.urls import path
from . import views
urlpatterns = [
path('', views.HomePageView.as_view(), name='home'),
path('new/', views.ArticleCreateView.as_view(), name='article_new'),
path('<int:pk>/', views.ArticleDetailView.as_view(), name='article_detail_view'),
path('<int:pk>/publish/', views.publish_article, name='publish_article'),
path('<int:pk>/unpublish/', views.unpublish_article, name='unpublish_article'),]
Here are my models.
from django.conf import settings
from django.db import models
from django.urls import reverse
from django import forms
class Article(models.Model):
name = models.CharField(max_length=255, blank=False)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
published = models.BooleanField(default=False)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('article_detail_view', args=[str(self.id)])
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['name',]
Lastly, here is the template.
{% extends 'base.html' %}
{% block title %}{{ article.name }}{% endblock %}
{% block content %}
{% if article.author_id == user.pk %}
<div class="row">
<div class="col-6 col-centered">
<h2 class="text-center">{{ article.name }}</h2>
<p class="text-center">by {{ article.author.first_name }} {{ article.author.last_name }}</p>
{% if article.published %}
<small class="form-text text-muted mb-1">This article is public.</small>
<form method="post" action="/articles/{{ article.pk }}/unpublish/">
{% csrf_token %}
<input type="submit" name="unpublish" value="Unpublish Article" id="id_unpublish_button" class="btn btn-primary btn-md"/>
</form>
{% else %}
<small class="form-text text-muted mb-1">This article is private.</small>
<form method="post" action="/articles/{{ article.pk }}/publish/">
{% csrf_token %}
<input type="submit" name="publish" value="Publish Article" id="id_publish_button" class="btn btn-primary btn-md"/>
</form>
{% endif %}
</div>
</div>
{% elif article.published %}
<div class="row">
<div class="col-6 col-centered">
<h2 class="text-center">{{ article.name }}</h2>
<p class="text-center">by {{ article.author.first_name }} {{ article.author.last_name }}</p>
</div>
</div>
{% else %}
<div class="row">
<div class="col-6 col-centered">
<p class="text-center">This article is private.</p>
</div>
</div>
{% endif %}
{% endblock %}
This is the error message I'm getting from my test. The issue seems to be I can post to the URL with self.client.post . Any help would be greatly appreciated.
FAIL: test_can_publish_article_from_POST (articles.tests.ArticleDetailViewTest)
Traceback (most recent call last):
File "/Users/christopher.chough/article_directory/articles/tests.py", line 126, in test_can_publish_article_from_POST
self.assertEqual(correct_article_two.published, True)
AssertionError: False != True
Ran 17 tests in 2.340s
FAILED (failures=1)
Object in your test method not updated. You can use refresh_from_db method to update it after changes:
def test_can_publish_article_from_POST(self):
other_article_two = Article.objects.create(name='Test Name One', author=User.objects.get(email='testuser#gmail.com'))
correct_article_two = Article.objects.create(name='Test Name Two', author=User.objects.get(email='testuser#gmail.com'))
response = self.client.post(reverse('publish_article', kwargs={'pk' : correct_article_two.pk}))
correct_article_two.refresh_from_db() # Add this line
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, f'/articles/{correct_article_two.pk}/')
self.assertEqual(correct_article_two.published, True)
I am attempting to create a custom template tag to display a comment. When I try submitting a reply through the form attached to each comment, I get an error:
Forbidden (403)
CSRF verification failed. Request aborted.
Reason given for failure:
CSRF token missing or incorrect.
The csrf token works on the form with the download and follow button, but not on the form generated from the template tag. Any help would be appreciated.
DocumentView
def DocumentView(request, doc_id):
context = {}
user = None
if request.user.is_authenticated():
email = request.user.email
id = request.user.id
user = get_user_information(email=email)
else:
user = None
context['user'] = user
if request.method == 'POST':
user_id = request.POST.get('submit', '')
doc = Doc.objects.get(id=doc_id)
doc_version = DocVersion.objects.filter(doc__id=doc_id).latest('id')
doc_title = doc.response_title
allow_comments = doc.allow_comments
comments = {}
if user['user_type'] == 'DA':
for comment in Comment.objects.filter(doc_id=doc_id):
comments[comment.id] = {'content': comment.content, 'reply_to': comment.reply_to, 'user_id': comment.user.id}
else:
for comment in Comment.objects.filter(doc_id=doc_id, is_flagged=False):
comments[comment.id] = {'content': comment.content, 'reply_to': comment.reply_to, 'user_id': comment.user.id}
context['comments'] = comments
context['allow_comments'] = allow_comments
context['doc_title'] = doc_title
print context
return render(request, 'doc/document.html', context)
comment_tags.py
from django.template import Library, Node, Context, Variable
from django.template.loader import get_template
from django import template
register = Library()
#register.tag()
def comments(parser, token):
user_id, profile_pic, reply_id, comment_id, content, info = None, None, None, None, "", ""
for index, x in enumerate(token.split_contents()):
if x == 'user_id':
user_id = token.split_contents()[index + 1]
if x == 'profile_pic':
profile_pic = token.split_contents()[index + 1]
if x == 'content':
content = token.split_contents()[index + 1]
if x == 'info':
info = token.split_contents()[index + 1]
if x == 'reply_id':
reply_id = token.split_contents()[index + 1]
if x == 'comment_id':
comment_id = token.split_contents()[index + 1]
return CommentNode(user_id, profile_pic, comment_id, content, info, reply_id)
class CommentNode(template.Node):
def __init__(self, user_id, profile_pic, comment_id, content, info, reply_id):
self.user_id = template.Variable(user_id)
self.profile_pic = template.Variable(profile_pic)
self.content = template.Variable(content)
self.info = template.Variable(info)
self.comment_id = template.Variable(comment_id)
if reply_id != None:
self.reply_id = template.Variable(reply_id)
else:
self.reply_id = reply_id
def render(self, context):
t = get_template("srd/comment.html")
if self.reply_id == None:
return t.render({
'user_id': self.user_id.resolve(context),
'profile_pic': self.profile_pic.resolve(context),
'comment_id': self.comment_id.resolve(context),
'content': self.content.resolve(context),
'info': self.info.resolve(context),
'reply_id': self.reply_id
}
)
else:
return t.render({
'user_id': self.user_id.resolve(context),
'profile_pic': self.profile_pic.resolve(context),
'comment_id': self.comment_id.resolve(context),
'content': self.content.resolve(context),
'info': self.info.resolve(context),
'reply_id': self.reply_id.resolve(context)
})
document.html
{% load static %}
{% load comment_tags %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ doc_title }}</title>
<link rel="stylesheet" type="text/css" href="{% static "stylesheets/doc.css" %}">
<script src="{% static "javascript/jquery-3.2.1.min.js" %}" type="text/javascript"></script>
<script src="{% static "javascript/doc.js" %}" type="text/javascript"></script>
</head>
<body>
<div class="main_div">
<div class="content_div">
<div class="info_div">
<h2>[{{ generic_name }}]</h2>
<label>{{ doc_title }} [Edit]</label>
</div>
<div class="doc_div">
<div class="doc_preview">
</div>
<div class="doc_preview_info">
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ user.id }}" />
<input type="submit" value="Donwload PDF" /><br/>
<input type="submit" value="Follow" />
</form>
</div>
</div>
{% if allow_comments %}
<div class="comment_div" id="comment_div">
{% for commentid, comment in comments.items %}
{% if comment.reply_to %}
{% comments comment_id commentid user_id comment.user_id reply_id comment.reply_to.id profile_pic "hi" content comment.content info "XYZ" %}
{% else %}
{% comments comment_id commentid user_id comment.user_id profile_pic "hi" content comment.content info "XYZ" %}
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
<div class="ad_div">
<div class="ad"></div>
<div class="ad"></div>
<div class="ad"></div>
<div class="ad"></div>
</div>
</div>
</body>
</html>
comment.html
<div class="comment">
<div class="profile_pic">
{{ user_id }}
</div>
<div class="comment_content">
<div class="top_bar">
<div class="comment_info">
{{ info }}
</div>
<div class="flag">
Flag
</div>
</div>
<div class="comment_text">
{{ content }}
</div>
<div class="reply_bar">
<a id="reply_link_{{ comment_id }}" class="reply_link" href="#">Reply</a>
</div>
</div>
</div>
<div class="reply" id="reply_{{ comment_id }}">
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ reply_id }}"/>
<input name="reply_text" type="text" />
<input type="submit" value="Post" />
</form>
</div>
Since you are rendering the template manually in your tag, you need to use a RequestContext so that it runs the context processors - including the one that adds the CSRF token.
return t.render(RequestContext(context['request'], {
...
}))
Note, the whole thing could be greatly simplified by using an inclusion tag.
Okay Guys, I have a custom User Registration form, whenever the form is submitted a browser alert pops up saying "The Page at 127.0.0.1:8000 says: Submitted!" and nothing happens. No data is saved. Following is the code of the Index view where i am trying to save the form:
def Index(request):
"""View to serve the index page."""
regform = models.RegistrationForm()
loginform = models.LoginForm()
if request.method == 'POST':
if 'signup' in request.POST:
form = models.RegistrationForm(request.POST)
if form.is_valid():
form.save()
message = 'Your Account has been created. You may login now.'
return shortcuts.render_to_response(
'index.html', {'message' : message, 'regform' : regform, 'loginform' : loginform})
else:
message = 'Error: Please fill in all the fields and try again'
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'message' : message, 'loginform' : loginform})
elif 'login' in request.POST:
requser = request.POST['loginemail']
reqpass = request.POST['loginpass']
'''check if email exists'''
emailexist = models.member.objects.filter(Email=requser).count()
if emailexist == 1:
exists = True
else:
exists = False
'''if email exists check for password'''
if exists == True:
mem = models.member.objects.get(Email=requser)
if reqpass == mem.Password:
request.session['member_id'] = mem.id
return shortcuts.render_to_response(
'login.html')
else:
error = 'You entered an invalid Password, Please try again.'
return shortcuts.render_to_response(
'index.html', {'error' : error, 'regform' : regform, 'loginform' : loginform})
else:
error = 'That E-mail Address is Not Registered, Please Check the spelling and try again.'
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'loginform' : loginform, 'error' : error})
else:
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'loginform' : loginform})
Sorry, Here's the Code to the model and registration form
Model:
class member(models.Model):
"""Model to represent a User."""
First_Name = models.CharField(max_length=100, blank=False)
Last_Name = models.CharField(max_length=100, blank=False)
Stage_Name = models.CharField(max_length=100, unique=True, blank=False)
Account_Type = models.CharField(max_length=200, choices=USERTYPE_CHOICES, blank=False)
Password = models.CharField(max_length=100, blank=False)
Email = models.EmailField(max_length=100, blank=False)
Sex = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=False)
Birthday = models.CharField(max_length=2, blank=False)
def __unicode__(self):
return self.Email
Registration Form:
class RegistrationForm(forms.ModelForm):
Stage_Name = forms.CharField(label='Username')
Email = forms.CharField(initial='you#example.com')
Birthday = forms.CharField(initial='dd/mm/yyyy')
Password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model=member
And here is the template :::::
{% extends 'base.html' %}
{% load login_checkbox %}
{% block topbar %}
<head>
</head>
<body>
<div id="logo" class="left"><img src="/static/images/logo.png" alt="Muzikube" width="200" height="52" border="0"/></div>
<div id="login" class="right">
<form id="loginform" action="." method="post">
{% for field in loginform %}
{% if field.field.widget|is_checkbox %}
<div class="checkbox">{{field}}{{field.label_tag}}<span id="forgotpass">Can't Sign In?</span></div>
{% else %}
{{field.label_tag}}{{field}}
{% endif %}
{% endfor %}
<input id="submit" class="submit" "type="submit" name="login" value="In!" />
</form>
{% if error %}
{{error}}
{% endif %}
</div>
<div class="clear"></div>
</body>
{% endblock topbar %}
{% block content %}
<body>
<div class="left">
<div id="heading">Connect To Other Musicians</div>
<div class="subheading">Upload your music, Share Pictures, Share Videos, Make Friends, Get Known !</div>
<div id="homepageimage"><img src="/static/images/comm.png" alt="Connect to other Musicians Around the world!" width="450" height=""/></div>
<div class="subheading">Muzikube let's you connect to other people around the world that share same interests as you !</div>
</div>
<div id="registrationform" class="right">
<div id="form-title">Sign Up, It's Free !</div>
<div id="form-subtitle">Connect to other musicians around the world.</div>
<div class="border"></div>
<div class="error">
{% if message %}
{{message}}
{% endif %}
</div>
<form id="regform" action="." method="post">
<table>
{{ regform.as_table }}
</table>
<input id="register-submit" class="submit" type="submit" name="signup" value="Sign Up" />
</form>
<div class="border"></div>
</div>
<div class="clear"></div>
</body>
{% endblock content %}
It's a little hard to tell from the code above, but I would guess that you get a POST that doesn't have 'login' or 'signup' in (I can't see why it would have those parameters from the code, maybe it's in the html?) - and so nothing is saved or returned from the post request.