displaying other attribute values if one is known in django template - python

i have this app in django that i'm trying to make. this is the index.html page
<html>
<head>
<title>The index page</title>
</head>
<body>
<h1>Choose the name of student</h1>
<form action= "{% url 'detail' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<select name="namedrop">
{% for name in student_list %}
<option value={{name.stuname}}>{{name.stuname}}</option>
{% endfor %}
</select>
<input type="submit" name="submit">
</form>
</body>
</html>
and this is the detail.html page to which it is directed when we select a name and click submit button...
<!DOCTYPE html>
<html>
<head>
<title>Details of student </title>
</head>
<body>
<p>hello {{name}}</p>
<style type="text/css">
p
{
color: blue;
}
</style>
</body>
</html>
but it only shows "hello neha" if the name selected is "neha"... but i want it to print all the details of this student from the table student...this is models.py...
from django.db import models
class course(models.Model):
cid=models.IntegerField(unique=True,default=0)
cname=models.CharField(max_length=50)
def __unicode__(self):
return self.cname
class Meta:
db_table= "course"
class student(models.Model):
stuid=models.IntegerField(default=0)
stuname=models.CharField(max_length=50)
cid=models.ForeignKey(course,to_field='cid',on_delete=models.CASCADE)
def __unicode__(self):
return self.stuname
class Meta:
db_table= "student"
class subject(models.Model):
sid=models.IntegerField(default=0)
sub=models.CharField(max_length=50)
cid=models.ForeignKey(course,to_field='cid',on_delete=models.CASCADE)
class Meta:
db_table= "subject"
def __unicode__(self):
return self.sub
this is views.py
from .models import student
from django.http import Http404
from django.shortcuts import render
from django.template import loader
from django.http import HttpResponse
def index(request):
student_list=student.objects.all()
template = loader.get_template('studinfo/index.html')
context= { 'student_list' : student_list, }
return HttpResponse(template.render(context, request))
def detail(request):
if request.method=='POST':
name=request.POST['namedrop']
idd=student.objects.all
return render(request, 'studinfo/detail.html', {'name':name})
also i want it to display all the subjects that "neha" has through the details.html page...how do i do that?

you need to select the student with the following query in your view detail:
student = student.objects.filter(stuname=name)[0]
and add the result to the context :
return render(request, 'studinfo/detail.html', {'name':name, 'student': student})
Then in your template, you can call
{{student.stuname}} or {{student.cid}} ...

In your index template you are passing the name in the form, and just use it in the view to pass it along to the detail template. You need to get the student object and pass it to the detail template, so you have accesss to all its fields. You could start by passing the id in the form, instead of the name:
{% for student in student_list %}
<option value={{ student.id }}>{{ student.stuname }}</option>
{% endfor %}
Then in the view you can do something like this (you would probably want to add more sanity checks, like making sure the student exists):
def detail(request):
if request.method=='POST':
student_id = request.POST['namedrop']
student_instance = student.objects.get(pk=student_id)
idd=student.objects.all
return render(request, 'studinfo/detail.html', {'student': student_instance})
Now in the detail template you have access to the student object and can use all its attributes (e.g. {{ student.stuname }}).
Since there is no direct connection between students and subjects, you have to go through the course:
{% for subject in student.cid.subject_set.all %}
{{ subject }}
{% endfor %}

Related

Django - How do you get the corresponding model object in a for loop in html?

I am trying to create a simple django website where any user can rate and create posts. As displayed in this django tutorial (https://docs.djangoproject.com/en/1.7/topics/templates/), you can display all the model objects in html using a for loop. In my case, each object is going to be displayed with a Like and a Dislike button, so people can rate the post. My problem is: How do I know which object belongs to which like/dislike button so that the corresponding model field can be changed for that particular object? Thank You for answers!
models.py
from django.db import models
# Create your models here.
class Post(models.Model):
post_text = models.CharField(max_length=500)
pub_date = models.DateTimeField("date published")
likes = models.IntegerField(default=0)
dislikes = models.IntegerField(default=0)
def __str__(self):
return self.post_text
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AllPosts</title>
</head>
<body>
{% if post_list %}
<ul>
{% for post in post_list %}
<li>{{post.post_text}}</li>
<p>This post has {{post.likes}} likes and {{post.dislikes}} dislikes.</p>
<br>Leave a <button type="button" method="LIKE">Like</button> or a <button type="button" method="DISLIKE">Dislike</button>!</p>
{% endfor %}
</ul>
<h2>If you want to create a post yourself, click here.</h2>
{% else %}
<h1>There are no posts yet...</h1>
{% endif %}
</body>
</html>
views.py
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.utils import timezone
from .models import Post
# Create your views here.
def index(request):
post_list = Post.objects.order_by('-pub_date')
template = loader.get_template('post/index.html')
context = {'post_list': post_list, }
#if request.method == "LIKE":
# post = Post.objects.get(id=) How do I find out the id?
# return HttpResponse(template.render(context, request))
#else:
return HttpResponse(template.render(context, request))
def create(request):
template = 'post/create.html'
if request.method == 'POST':
post = Post()
post.post_text = request.POST.get("post_text")
post.pub_date = timezone.now()
post.save()
return render(request, template)
else:
return render(request, template)
In order for the buttons to work, they need to be inside a form element and be of type="submit" otherwise they won't do anything when clicked. To identify which button was clicked, you can then replace the method attributes with name="like" and name="dislike". The buttons can then be referenced to the related post by setting their value to the post ID.
Below is an example of the code that should do this. I've clipped out some of the unrelated parts of the code. (Note: I haven't tested this, so it may not work perfectly)
index.html UL element:
<ul>
{% for post in post_list %}
<li>
<span>{{post.post_text}}</span><br>
<p>This post has {{post.likes}} likes and {{post.dislikes}} dislikes.</p>
<form method="post">
<p>
Leave a <button type="submit" name="like" value="{{post.id}}">Like</button>
or a <button type="submit" name="dislike" value="{{post.id}}">Dislike</button>!
</p>
</form>
</li>
{% endfor %}
</ul>
views.py index:
def index(request):
if request.method == 'POST':
like = request.POST.get('like')
dislike = request.POST.get('dislike')
if like:
# Handle liked post
# `like` is equal to the post ID
else if dislike:
# Handle disliked post
# `dislike` is equal to the post ID
else:
# No action requested
else:
post_list = Post.objects.order_by('-pub_date')
template = loader.get_template('post/index.html')
context = {'post_list': post_list, }
return HttpResponse(template.render(context, request))
I hope this helps :)

Django - saving form to the built in database SQLite

This is my first time using Django and I am very simply trying to save text to the database. I have created the table inputs in the database.
I am getting the following error;
Error - Page not found (404)
My code is as follows;
Models.py
from django.db import models
class Input(models.Model):
waist = models.IntegerField(default=0)
height = models.IntegerField(default=0)
def __unicode__(self):
return "{0} {1} {2}".format(
self, self.waist, self.height)
forms.py
class InputForm(forms.ModelForm):
class Meta:
model = Input
fields ={
'waist',
'height'
}
views.py
def InputView(request):
if request.POST:
form = InputForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('account/input')
else:
form = InputForm()
args = {'form' : form}
return render(request,'accounts/input.html', args)
urls.py
url(r'^input/$',views.InputView, name='view_input')
input.html
{% extends 'base.html' %}
{% block head %}
<title> Edit Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<h1> Enter Body Details </h1>
<br>
<br>
<form action="account/input" method="post">
{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="Submit" name="submit" value="submit"/>
</form>
</div>
{% endblock %}
If any one can help it would be greatly appreciated.
HttpResponseRedirect('account/input')
you need to add one more '/' to the beginning like
HttpResponseRedirect('/account/input')
Another way to do it is to use reverse() so if you change the URL you don't have to change your code and you avoid mistakes entering the URL.
Instead of
HttpResponseRedirect('/account/input')
use
HttpResponseRedirect(reverse('view_input'))
remember to add the import
from django.urls import reverse

Having trouble with Django forms "OperationalError: no such table" error

I'm trying to set up a form on Django that displays inputs on the page, but I get this error.
django.db.utils.OperationalError: no such table: firstapp_post
This doesn't happen right away, but when I try to use the submit feature on my form.
Right now this is what I have as my models:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
post = models.CharField(max_length=500)
user = models.ForeignKey(User)
These are currently my forms:
from django import forms
from firstapp.models import Post
class IndexForm(forms.ModelForm):
post = forms.CharField()
class Meta:
model = Post
fields = ('post',)
This is my views file:
from django.shortcuts import render, redirect
from firstapp.forms import IndexForm
from django.views.generic import TemplateView
class HomePage(TemplateView):
template_name = 'home/home.html'
def get(self, request):
form = IndexForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = IndexForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
text = form.cleaned_data['post']
form = IndexForm()
return redirect('home:home')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
This is my base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Assignment 4</title>
<link rel='stylesheet' href='{% static "css/base.css" %}'/>
</head>
<body>
<p>{{ variable }}</p>
{% block body %}{% endblock %}
<script src= '{% static "js/base.js" %}'></script>
</body>
</html>
and my home.html:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<p>Home</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
<p>{{ text }}</p>
</div>
{% endblock %}
Does anyone have any idea what this error even means or why I'm getting it? This has been driving me nuts. Thanks for the help!
As the error message mentions, that particular table does not exist in your database.
You can run the following command:
python manage.py makemigrations appname
By running makemigrations, you’re telling Django that you’ve made some changes to your models and that you’d like the changes to be stored as a migration.
Now run migrate again to create those model tables in your database
python manage.py migrate
Further Reading

How to get class variable to Django template

I have just started with creating Django app. I have a class in models.py, which have a class variable CATEGORY_CHOICES with values for choices field.
#models.py
from django.db import models
from django.utils import timezone
class Entry(models.Model):
CATEGORY_CHOICES = (
('c1','choice 1'),
('c2','choice 2'),
('c3','choice 3'),
('c4','choice 4'),
)
date = models.DateField(default=timezone.now)
time = models.TimeField(default=timezone.now)
category = models.CharField(choices=CATEGORY_CHOICES,blank=False,null=False,max_length=2)
value = models.TextField()
I want to make form for creting instanes of class Entry. I'm having problem with the select menu, where I want to put values from CATEGORY_CHOICES but I can't figure out how.
<!-- homepage.html -->
{% load staticfiles %}
{% load app_filters %}
<HTML>
<HEAD>
<TITLE>Website title</TITLE>
<link rel="stylesheet" href="{% static "css/app.css" %}">
</HEAD>
<BODY>
<form method="POST" class="form-inline">{% csrf_token %}
<input type="date" class="form-control" id="date-input">
<input type="time" class="form-control" id="time-input">
<select class="form-control">
{% for choice in Entry.CATEGORY_CHOICES %}
<option>{{ choice|get_at_index:1 }}</option>
{% endfor %}
</select>
<input type="text" class="form-control" id="value-input" placeholder="Value">
<input type="submit" value="OK">
</form>
</BODY>
</HTML>
It's a 4 elements list, so {% for choice in Entry.CATEGORY_CHOICES %} should be saving single 2-elements lists (first ('c1','choice 1') then ('c2','choice 2') etc) into variable choice. There I pick the second element of the list with the help od custom filter get_at_index.
#app_filters.py
from django import template
register = template.Library()
#register.filter(name='get_at_index')
def get_at_index(list, index):
return list[index]
I get no errors, but in the final form, there are no options in select menu.
What could be wrong and how to fix it?
#views.py
from django.shortcuts import render
from .forms import EntryForm
def home_page(request):
form = EntryForm()
return render(request, 'app/homepage.html', {'form':form})
And forms.py
#forms.py
from django import forms
from .models import Entry
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ('date','time','category','value',)
In your view, you're passing down the form to the template, but you don't use the form in your template the way you're supposed to. To use the form you've passed down, write your form code in the template more like this:
<form method="POST" class="form-inline">
{% csrf_token %}
{{ form }}
<input type="submit" value="OK">
</form>
And it will render the entire form for you. You can read more about it in the official documentation: Building a form in Django
Or, if you want to build the form yourself, then you need to send the coices down to your template in your view:
def home_page(request):
form = EntryForm()
return render(request, 'app/homepage.html', {
'form': form,
'entry_choices': Entry.CATEGORY_CHOICES
})
And then access it in your template using the key entry_choices.

Tango with Django - Chapter 8 - Exercise

I need some help getting the add_page function to work properly. I am very new to HTML and even newer to Django. The chapter I am working on can be found here: http://www.tangowithdjango.com/book17/chapters/forms.html. Currently my relevent files look like this:
Forms.py
from django import forms
from rango.models import Page, Category
class CategoryForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="Please enter the category name.")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput(), required=False)
# An inline class to provide additional information on the form.
class Meta:
# Provide an association between the ModelForm and a model
model = Category
fields = ('name',)
class PageForm(forms.ModelForm):
title = forms.CharField(max_length=128, help_text="Please enter the title of the page.")
url = forms.URLField(max_length=200, help_text="Please enter the URL of the page.")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
class Meta:
# Provide an association between the ModelForm and a model
model = Page
# What fields do we want to include in our form?
# This way we don't need every field in the model present.
# Some fields may allow NULL values, so we may not want to include them...
# Here, we are hiding the foreign key.
# we can either exclude the category field from the form,
exclude = ('category',)
#or specify the fields to include (i.e. not include the category field)
#fields = ('title', 'url', 'views')
def clean(self):
cleaned_data = self.cleaned_data
url = cleaned_data.get('url')
# If url is not empty and doesn't start with 'http://', prepend 'http://'.
if url and not url.startswith('http://'):
url = 'http://' + url
cleaned_data['url'] = url
return cleaned_data
Views.py:
from django.shortcuts import render
from django.http import HttpResponse
from rango.models import Category, Page
from rango.forms import CategoryForm, PageForm
def index(request):
# Query the database for a list of ALL categories currently stored.
# Order the categories by no. likes in descending order.
# Retrieve the top 5 only - or all if less than 5.
# Place the list in our context_dict dictionary which will be passed to the template engine.
category_list = Category.objects.order_by('-likes')[:5]
page_list = Page.objects.order_by('-view')[:5]
context_dict = {'categories': category_list,
'pages': page_list}
# Render the response and send it back!
return render(request, 'rango/index.html', context_dict)
def category(request, category_name_slug):
# Create a context dictionary which we can pass to the template rendering engine.
context_dict = {}
try:
# Can we find a category name slug with the given name?
# If we can't, the .get() method raises a DoesNotExist exception.
# So the .get() method returns one model instance or raises an exception.
category = Category.objects.get(slug=category_name_slug)
context_dict['category_name'] = category.name
context_dict['category_name_slug'] = category_name_slug
# Retrieve all of the associated pages.
# Note that filter returns >= 1 model instance.
pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
context_dict['pages'] = pages
# We also add the category object from the database to the context dictionary.
# We'll use this in the template to verify that the category exists.
context_dict['category'] = category
except Category.DoesNotExist:
# We get here if we didn't find the specified category.
# Don't do anything - the template displays the "no category" message for us.
pass
# Go render the response and return it to the client.
print context_dict
return render(request, 'rango/category.html', context_dict)
def add_category(request):
# A HTTP POST?
if request.method == 'POST':
form = CategoryForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save(commit=True)
# Now call the index() view.
# The user will be shown the homepage.
return index(request)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = CategoryForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'rango/add_category.html', {'form': form})
def add_page(request, category_name_slug):
try:
cat = Category.objects.get(slug=category_name_slug)
except Category.DoesNotExist:
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit=False)
page.category = cat
page.views = 0
page.save()
# probably better to use a redirect here.
return category(request, category_name_slug)
else:
print form.errors
else:
form = PageForm()
context_dict = {'form':form, 'category': cat}
return render(request, 'rango/add_page.html', context_dict)
urls.py
from django.conf.urls import patterns, url
from rango import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
# url(r'^about/$', views.about, name='about'),
url(r'^add_category/$', views.add_category, name='add_category'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/add_page/$', views.add_page, name='add_page'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category'),)
I think this ^ is where I am encountering the issue. I manage to get to the "add a page" screen, but when I try to submit something, I receive an error that states I am only supplying 1 argument and add_page() requires 2. I think I may need an additional url that is similar to the "add_category" URL, but that must mean by other URL is pointing to the wrong place?
category.html
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>{{ category_name }}</h1>
{% if category %}
{% if pages %}
<ul>
{% for page in pages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
{% else %}
<strong>No pages currently in category.</strong>
{% endif %}
<li>Add a New Page</li>
{% else %}
The specified category {{ category_name }} does not exist!
{% endif %}
</body>
</html>
add_page.html:
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/add_page/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
I edited the add_page function to include category_name_slug:
def add_page(request, category_name_slug):
try:
cat = Category.objects.get(slug=category_name_slug)
except Category.DoesNotExist:
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit=False)
page.category = cat
page.views = 0
page.save()
# probably better to use a redirect here.
return category(request, category_name_slug)
else:
print form.errors
else:
form = PageForm()
# made the change here
context_dict = {'form':form, 'category': cat, 'category_name_slug': category_name_slug}
return render(request, 'rango/add_page.html', context_dict)
Then I edited the add_page.html to look like this:
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/category/{{ category_name_slug }}/add_page/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
if you dont wanna edit your views.py
just doit
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/category/{{ category }}/add_page/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
but i have problem to it still cannot be save on database.

Categories

Resources