I have set of questions and its answers stored in db.I have a form to get answer for each question.I need to display only one question at a time in template and validate that answer against the original answer stored in db.
For now am able to display one value.But what i need is to display a question in a page and validate if the answer is correct,move on to display next question from db and so on. How do I achieve this?
form.py
from django import forms
class details_form(forms.Form):
answer = forms.CharField(widget=forms.TextInput())
views.py
def display_question(request):
context = RequestContext(request)
if request.method == 'GET':
print "GET"
form_class = details_form()
que_data = details.objects.get(que_id=1)
else:
##POST request
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data},context)
template:
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action='/next'>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
Update:
views.py
def display_question(request,question_id):
context = RequestContext(request)
form_class = details_form()
try:
quesno_id = {'id':question_id}
que_data = details.objects.get(que_id=question_id)
except details.DoesNotExist:
pass
if request.method == 'POST':
form = details_form(request.POST)
if form.is_valid():
user_answer = form.cleaned_data['answer']
if que_data.original_answer == user_answer:
return HttpResponseRedirect("question/%s/" %question_id+1)
else:
print form.errors
else:
pass
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data,'quesno_id':quesno_id},context)
template
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question {{ quesno_id.id}} : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action="/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
urls.py
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^question/(?P<question_id>\w+)/$',views.display_question,name='display_question'),
)
models.py
from django.db import models
class Songdata(models.Model):
que_id = models.AutoField(primary_key=True)
que = models.CharField(max_length=256)
original_answer = models.TextField()
def __unicode__(self):
return self.song_name
form.py
from django import forms
class details_form(forms.Form):
user_answer = forms.CharField(widget=forms.TextInput())
You need to use an absolute URL path like HttpResponseRedirect("/question/%s/" % (question_id+1)) (notice the leading slash)
Related
One of functionality in my training project:
subscribe to the news by check-box and e-mail.
Send newsletter daily.
The user can unsubscribe from the mailing list in his profile by unchecking the checkbox.
It so happened that first I set up a daily newsletter for users who have booleanfield = true.
For it I marked the checkboxes in the admin panel. It works.
Now it is necessary to add the checkbox and the mail field to the news page.
I'm stuck on the simplest. Tired and confused.
Please help me place a checkbox and a mail box with a send button on the news page
models.py
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
hr = models.BooleanField(default=False)
subscribed_for_mailings = models.BooleanField(default=False)
subscription_email = models.EmailField(default="")
def __str__(self):
return str(self.user)
Forms.py
class MailingForm(forms.ModelForm):
class Meta:
model = models.Profile
fields = ('subscription_email', 'subscribed_for_mailings', )
widgets = {
'subscription_email': forms.EmailInput(attrs={"placeholder": "Your Email..."}),
'subscribed_for_mailings': forms.CheckboxInput,
}
views.py
def all_news(request):
today = date.today()
today_news = models.TopNews.objects.filter(created__gte=today)
return render(request, "news.html",
{'today_news': today_news})
def mailing_news(request):
if request.method == 'POST':
mailing_form = forms.MailingForm(request.POST)
if mailing_form.is_valid():
mailing_form.save()
return HttpResponse('You will receive news by mail')
else:
mailing_form = forms.MailingForm()
return render(request, "news.html", {'mailing_form': mailing_form})
urls.py
...
path('news/', views.all_news, name='all_news'),
...
news.html
{% extends 'base.html' %}
{% block title %}
News
{% endblock %}
{% block body %}
<h1>Last news</h1>
{% for news in today_news%}
<h3>{{ news.title }}</h3>
Read this news
<p>
{{ news.created }}
</p>
<hr>
{% endfor %}
<h4>I want to receive news by mail</h4>
<form action="." method="post">
{{ mailing_form.as_p }}
{% csrf_token %}
<label>
<input type="submit" value="Subscribe">
</label>
</form>
{% endblock %}
The page displays a list of news and only the "send" button. There is no check-box and a field for mail
enter image description here
Finally I realized this functionality in a different way:
forms.py
class MailingForm(forms.ModelForm):
class Meta:
model = models.Profile
fields = ('subscribed_for_mailings', 'subscription_email', )
views.py
#login_required
def mailing_news(request):
if request.method == "POST":
mailing_form = forms.MailingForm(request.POST,
instance=request.user.profile,
)
if mailing_form.is_valid():
mailing_news = mailing_form.save(commit=False)
mailing_news.subscribed_for_mailings = mailing_news.subscribed_for_mailings
mailing_news.subscription_email = mailing_news.subscription_email
mailing_news.save()
return render(request, "subscribe_complete.html",
{"mailing_news": mailing_news})
else:
mailing_form = forms.MailingForm()
return render(request, 'subscribe.html', {"mailing_form": mailing_form})
news.html
{% extends 'base.html' %}
{% block title %}
News
{% endblock %}
{% block body %}
<h1>Last news</h1> {{ news.created }}
{% for news in today_news%}
<h3>{{ news.title }}</h3>
Read this news
<hr>
{% endfor %}
I want to receive news by mail
{% endblock %}
urls.py
...
path('subscribe/', views.mailing_news, name='subscribe')
...
news.html
{% extends 'base.html' %}
{% block title %}
News
{% endblock %}
{% block body %}
<h1>Last news</h1> {{ news.created }}
{% for news in today_news%}
<h3>{{ news.title }}</h3>
Read this news
<hr>
{% endfor %}
I want to receive news by mail
{% endblock %}
subscribe.html
{% extends 'base.html' %}
{% block title %}
Subscribe
{% endblock %}
{% block body %}
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ mailing_news.as_p }}
{% if user.profile.subscribed_for_mailings is True %}
<input type="checkbox" name="subscribed_for_mailings" id="id_subscribed_for_mailings" checked="">
If you don't want to receive emails anymore, uncheck
<br>
Subscription email: <input type="email" name="subscription_email" value={{ user.profile.subscription_email }} class="vTextField" maxlength="254" id="id_subscription_email">
{% else %}
<label>
<input type="checkbox" name="subscribed_for_mailings" id="id_subscribed_for_mailings">
I want to subscribe for mailing news
</label>
<p><label>
Send news on my email:
<input type="email" name="subscription_email" class="vTextField" maxlength="254" id="id_subscription_email">
</label></p>
{% endif %}
<p><input type="submit" value="Update"></p>
</form>
{% endblock %}
subscribe_complete.html
{% extends 'base.html' %}
{% block title %}
Subscribing complete
{% endblock %}
{% block body %}
<h3>Hi {{ user.username }}</h3>
Thanks for subscribing.
You will receive daily news by email: {{ user.profile.subscription_email }}
{% endblock %}
you need to change subscribed_for_mailings in mailing news, like this
def mailing_news(request):
if request.method == 'POST':
mailing_form = forms.MailingForm(request.POST)
if mailing_form.is_valid():
profile = mailing_form.save(commit=False) ####
profile.subscribed_for_mailings = mailing_form.cleaned_data.get('subscribed_for_mailings') ####
profile.subscription_email = mailing_form.cleaned_data.get('subscription_email') ####
profile.save() #### new_line
return HttpResponse('You will receive news by mail')
else:
mailing_form = forms.MailingForm()
return render(request, "news.html", {'mailing_form': mailing_form})
you can change in cleaned_data.get('....')
I just want to put the username of the logged in user inside the author field and at the same time assign the author field as the user's username in the database.
def create_vacation(request):
form = creationForm(request.POST or None)
vacations = Vacation.objects.all()
vacations.author=request.user.username
if form.is_valid():
form.save()
return redirect('/vacations/all')
return render(request, 'creationForm.html', {'form': form})
and this is the vacation model
class Vacation(models.Model):
vacationInformation = models.TextField()
startDate= models.DateTimeField('start date')
endDate = models.DateTimeField('end date')
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self. vacationInformation
this is the form template
<form method="post" novalidate>
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
{% if vacation %}
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
I can render all of the vacation data in the homepage normally except for sure the author name
{% for vacation in vacations %}
<tr>
<td>{{ vacation.vacationInformation }}</td>
<td>{{ vacation.startDate }}</td>
<td>{{ vacation.endDate }}</td>
<td>{{ vacation.author }}</td>
It is giving me the entire user names in the author field in the form but I just want the user whom is logged in.
You need to get the currently logged in User. Then you can use the User to fill in the initial values in the form.
from django.contrib.auth import get_user
# ...
def create_vacation(request):
if request.method == 'POST':
form = creationForm(request.POST)
if form.is_valid():
form.save()
return redirect('/vacations/all')
else:
# Get the currently logged-in User.
user = get_user(request)
# Provide User as initial data to the form
form = creationForm(initial={'author': user})
return render(request, 'creationForm.html', {'form': form})
Relevant documentation:
ModelForm - Providing initial values
django.contrib.auth.get_user
I want to display the necessary field errors when the user who is populating the form does not enter valid information into the forms.
However, each I time I test the error script by clicking the submit button without populating any of the fields I get this error :
UnboundLocalError at /nesting/ local variable 'content' referenced
before assignment
How do I correct this?
This is my code :
veiws.py
from django.shortcuts import render, redirect
from django.views.generic import TemplateView
from nesting.forms import Identity_form
from nesting.models import Identity_unique
class Identity_view(TemplateView):
template_name = 'nesting/nesting.html'
def get(self, request):
form = Identity_form()
Identities = Identity_unique.objects.filter(user = request.user)
var = {'form': form, 'Identities': Identities}
return render(request, self.template_name, var)
def post(self, request):
form = Identity_form(request.POST or None)
if form.is_valid():
NIS = form.save(commit = False)
NIS.user = request.user
NIS.save()
content = form.cleaned_data['NIS']
form = Identity_form()
return redirect('nesting:nesting')
var = {'form': form, 'content': content}
return render(request,self.template_name, var)
The error messages is saying the error is caused by this line
var = {'form': form, 'content': content}
return render(request,self.template_name, var)
nesting.html
{% extends 'base.html' %}
{% load widget_tweaks %}
<html>
<head>
{% block head %}
<title>nesting</title>
{% endblock %}
</head>
<body>
{% block body %}
<div class = "container" style = "margin-top: 80px;">
<form method = 'post' novalidate>
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
<div class = "col-sm-8 col-md-8 col-lg-6">
<p class = "font-weight-bold">Create Patient</p>
{% if form.non_field_errors %}
<div class = "alert alert-danger" role = "alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class = "form-group">
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class = "invalid-feedback ">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class = "form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<button class = "btn-primary btn-large btn ">Submit</button>
</div>
</form>
</div>
<div class = "col-sm-8 col-md-6 col-lg-6">
{% for Identity in Identities %}
<div class = "card" style = "margin-top: 40px;">
<div class = "card-header">
<p class="font-weight-bold"> {{Identity.First_Name}} {{Identity.Last_Name}} </p>
</div>
<div class = "card-body">
<div class = "card-title">
<p class = "font-weight-light" style = "font-family: Optima">National Insurance Scheme : {{ Identity.NIS }}</p>
</div>
<p><small class = "card-text">Created On : {{ Identity.Timestamp }}</small></p>
<p><small class = "card-text">Address : {{ Identity.Residence }}</small></p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
</body>
</html>
In your views. content is referenced in var = {'form': form, 'content': content}. It is only instantiated after if form.is_valid() block.
The unboundError occurs when your form is invalid, then the var = {'form': form, 'content': content} does not have any variable named content to refer to.
The Fix: instantiate content before the if form.is_valid() block.
content = None
When I click on my delete project link it takes me to my delete page with a button to click which should delete the model data of the project and then take me to the profile page. However when I click the delete button, the page just refreshes and no data gets deleted?!
What am I doing wrong here? Any help would be much appreciated :-)
Views
class DeleteProject(UpdateView):
model = UserProject
template_name = 'howdidu/delete_project.html'
def get_object(self, queryset=None):
obj = super(DeleteProject, self).get_object()
if not obj.user == self.request.user:
raise Http404
return obj
def get_success_url(self):
project_username = self.request.user.username
#project_slug = self.object.slug
return reverse('user_profile', kwargs={'username':project_username})
delete_project.html template
{% extends 'howdidu/base.html' %}
{% load staticfiles %}
{% block title %}Delete project{% endblock %}
{% block body_block %}
<h1>Delete project</h1>
<form method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ userproject.title }}"?</p>
<input type="submit" value="Confirm" />
</form>
{% endblock %}
Urls
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^register_profile/$', views.register_profile, name='register_profile'),
url(r'^update_profile/$', views.update_profile, name='update_profile'),
url(r'^create_project/$', login_required(views.CreateProject.as_view()), name='create_project'),
url(r'^(?P<username>\w+)/(?P<slug>[-\w]+)/update_project/$', login_required(views.UpdateProject.as_view()), name='update_project'),
url(r'^(?P<username>\w+)/(?P<slug>[-\w]+)/delete_project/$', login_required(views.DeleteProject.as_view()), name='delete_project'),
url(r'^(?P<username>\w+)/$', views.profile_page, name='user_profile'),
url(r'^(?P<username>\w+)/(?P<slug>[-\w]+)/$', views.project_page, name='user_project'),
)
Project.html template which has the delete link on
{% extends 'howdidu/base.html' %}
{% load staticfiles %}
{% block title %}Project{% endblock %}
{% block body_block %}
{% if project %}
<h1>{{ project.title }}</h1>
<img src="{{ project.project_picture.url }}" width = "300" height = "300" />
<h3>{{ project.project_overview }}</h3>
{% if user.is_authenticated %}
{% if project_user.username == user.username %}
<p>Edit project</p>
<p>Delete project</p>
{% endif %}
{% endif %}
{% else %}
The specified project {{ project.title }} does not exist!
{% endif %}
{% endblock %}
You must use DeleteView not UpdateView.
See here.
I'm using the app django-likes and have managed to get it working. But I'm running into a very weird problem. The model "Story" is associated with the likes. Now the Story posts are repeated the number of votes they have -- for example, if they have 4 votes, they're actually repeated 4 times. Not sure what's going on. Any help much appreciated.
views.py
def home(request):
posts = Story.objects.all().order_by('votes')
form = StoryForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
messages.success(request, 'Thanks for adding your mix!')
return render_to_response('home.html',
locals(),
context_instance=RequestContext(request))
models.py
from django.db import models
import secretballot, likes
class Story(models.Model):
text = models.CharField(max_length=2000)
def __unicode__(self):
return self.text
secretballot.enable_voting_on(Story)
home.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load likes_inclusion_tags %}
{% block content %}
{% if user.is_authenticated %}
<h1 align=center>Add Your Mix!</h1>
<div class='col-sm-6 col-sm-offset-3'>
<h1>{{ form_title }}</h1>
<form method="POST" action="" >{% csrf_token %}
{{ form|crispy }}
<input type='submit' class='btn' value='Add{{ button_submit }}' />
</form>
</div>
{% else %}
<h1 align=center>Login and add a story!</h1>
<p align=center><a class="btn btn-primary btn-lg" href="/accounts/login/" role="button">Login!</a></p>
{% endif %}
{% for post in posts %}
<p>{{ post.text }} {% likes post %}</p>
{% endfor %}
{% endblock %}
It is possible that the {% likes post %}returns a number and Multiplies the string {{ post.text }} five times like python would. Try separating it or converting it to string.