How to render to template with dropdownbox in django? - python

I'm a beginner Django. And I got a problem with rendering to the template.
I have a model(models.py) which has the class "FuelInfo"; includes ForeignKey.
from django.db import models
class Traveler(models.Model):
traveler_name = models.CharField(max_length=10)
def __str__(self):
return self.traveler_name
class FuelInfo(models.Model):
name = models.ForeignKey(Traveler, on_delete=models.SET_NULL, null=True)
car = models.CharField(null=True, max_length=50)
efficiency = models.FloatField()
def __str__(self):
return str(self.name)
Also views.py is like :
from django.shortcuts import render, get_object_or_404
from .models import FuelInfo
def traveler_list(request):
travelers = FuelInfo.objects.all()
context = {'travelers':travelers}
return render(request, 'fuelcost/home.html', context)
def traveler_detail(request, pk):
traveler = get_object_or_404(FuelInfo, pk=pk)
return render(request, 'fuelcost/calfuel.html', {'traveler': traveler})
And urls.py is :
from django.urls import path
from . import views
app_name = 'fuelcost'
urlpatterns = [
path('', views.traveler_list, name='home'),
path('<int:pk>/', views.traveler_detail, name='calfuel'),
]
I want to make a dropdown that is render to template "calfuel.html" in home.html.
So I made a template("home.html") like :
{% extends "base_generic.html" %}
{% block content %}
<body>
{% if travelers %}
<form method="POST" action="{% url 'fuelcost:calfuel' pk=traveler.pk %}">
{% csrf_token %}
<select name="traveler">
{% for traveler in travelers %}
<option value="{{ traveler.id }}">{{ traveler.name }}</option>
{% endfor %}
</select>
<input type="submit" value="Select" />
</form>
{% else %}
<p>No travelers are available</p>
{% endif %}
</body>
{% endblock %}
But it doesn't works and i received error.
(My urlpattern is fuelcost/.)
Actually I can go into fuelcost/1 or fuelcost/2 that is views.traveler_detail named "calfuel". But I can't go into fuelcost/ that is views.traveler_list named "home".
I don't know what I have to do more. plz, tell me what is wrong with this.

{% block content %}
<body>
{% if travelers %}
{% for traveler in travelers %}
<form method="POST" action="{% url 'fuelcost:calfuel' pk=traveler.pk %}">
{% csrf_token %}
<select name="traveler">
<option value="{{ traveler.id }}">{{ traveler.name }}</option>
</select>
<input type="submit" value="Select" />
</form>
{% endfor %}
{% else %}
<p>No travelers are available</p>
{% endif %}
</body>
{% endblock %}
you have to keep the form inside loop so that it can get pk of traveler

Related

Comments in the admin panel are added, but they are not visible on the site

Based on this tutorial https://www.youtube.com/watch?v=An4hW4TjKhE&ab_channel=AbhishekVerma
I'm trying to add the ability to add comments under posts, add a comment in the admin panel, everything is ok, but the site does not display anything under the post
here is models.py
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
class Post(models.Model):
published = None
title = models.CharField(max_length=200)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = models.TextField()
header_image = models.ImageField(blank=True, null=True, upload_to="images/", default='fox.jpeg')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[str(self.id)])
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='post_post')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_user')
content = models.TextField(max_length=160)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}-{}'.format(self.post.title, str(self.user.username))
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Post, Comment
from django import forms
from .forms import *
class BlogListView(ListView):
model = Post
template_name = 'home.html'
context_object_name = 'posts'
paginate_by = 2
queryset = Post.objects.all()
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = ['title', 'author', 'body', 'header_image']
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body', 'header_image']
class BlogDeleteView(DeleteView):
model = Post
template_name = 'post_delete.html'
success_url = reverse_lazy('home')
#property
def image_url(self):
"""
Return self.photo.url if self.photo is not None,
'url' exist and has a value, else, return None.
"""
if self.image:
return getattr(self.photo, 'url', None)
return None
def post_detail(request, id, slug):
post = get_object_or_404(Post, id=id, slug=slug)
comments = Comment.objects.filter(post=post).order_by('-id')
is_liked = False
if post.likes.filter(id=request.user.id).exists():
is_liked = True
if request.method == 'POST':
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
content = request.POST.get('content')
comment = Comment.objects.create(post=post, user=request.user, content=content)
comment.save()
return HttpResponseRedirect(post.get_absolute_url())
else:
comment_form = CommentForm()
context = {
'post': post,
'is_liked': is_liked,
'total_likes': post.total_likes(),
'comments': comments,
'comment_form': comment_form,
}
return render(request, 'myblog/post_detail.html', context) #his "blog" = my "myblog"
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('content',)
post_detail.html
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
<p>+ Edit Blog Post</p>
<p>+ Delete Blog Post</p>
<img src="{{ post.header_image.url|default_if_none:'fox.jpeg' }}">
{{ post.body|urlize }}
{% for comm in post.commentpost_set.all%}
{{ comm.user }} <br>
{{ comm.text }} <br><br>
{% endfor %}
{% endblock content %}
<br><br>
<hr>
<form method="post">
{% csrf_token %}
{{ comment_form.as_p }}
{% if request.user.is_authenticated %}
<input type="submit" value="Submit" class="btn btn-outline-success">
{% else %}
<input type="submit" value="Submit" class="btn btn-outline-success" disabled>
{% endif %}
</form>
<div class="main-comment-section">
{{ comments.count }} Comment{{ comments|pluralize }}
{% for comment in comments %}
<blockquote class="blockquote">
<p class="mb-0">{{ comment.content }}</p>
<footer class="blockquote-footer">by <cite title="Source Title">{{ comment.user|capfirst }}</cite></footer>
</blockquote>
{% endfor %}
</div>
myblog/urls.py
from django.urls import path
from .views import (
BlogListView,
BlogDetailView,
BlogCreateView,
BlogUpdateView,
BlogDeleteView,
)
urlpatterns = [
path('post/new/', BlogCreateView.as_view(), name='post_new'),
path('post/<int:pk>/', BlogDetailView.as_view(), name='post_detail'),
path('post/<int:pk>/edit/',BlogUpdateView.as_view(), name='post_edit'),
path('post/<int:pk>/delete/',BlogDeleteView.as_view(), name='post_delete'),
path('', BlogListView.as_view(), name='home'),
]
base.html
{% load static %}
<html>
<head>
<title>Django blog</title>
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400"
rel="stylesheet">
<link href="{% static 'css/base.css' %}" rel="stylesheet">
</head>
<body>
<div>
<header>
<div class="nav-left">
<h1>Django blog</h1>
<h2>Admin</h2>
</div>
<div class="nav-right">
+ New Blog Post
</div>
</header>
{% if user.is_authenticated %}
<p>Hi {{ user.username }}!</p>
{% else %}
<p>You are not logged in.</p>
Log In<br>
<p>Sign up</p>
{% endif %}
{% block content %}
{% endblock content %}
</div>
</body>
</html>
<ul class="pagination">
{% if page_obj.has_previous %}
{% if page_obj.number|add:'-3' > 1 %}
<li class="pagination__item">
1
</li>
{% endif %}
{% if page_obj.number|add:'-3' >= 3 %}
<li class="pagination__item pagination__item--dots">
<a href="?{{ genre }}{{ year }}page={{ page_obj.previous_page_number|add:'-3' }}">
<span class="pagination__link">• • •</span>
</a>
</li>
{% endif %}
{% endif %}
{% if paginator.page_range|length > 1 %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="pagination__item active">
<a class="pagination__link" href="#">{{ i }}</a>
</li>
{% elif i > page_obj.number|add:'-4' and i < page_obj.number|add:'4' %}
<li class="pagination__item">
<a class="pagination__link" href="?{{ genre }}{{ year }}page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
{% if page_obj.has_next %}
{% if page_obj.number|add:'4' < page_obj.paginator.num_pages %}
<li class="pagination__item pagination__item--dots">
<a href="?{{ genre }}{{ year }}page={{ page_obj.next_page_number|add:'3' }}">
<span class="pagination__link">• • •</span>
</a>
</li>
{% endif %}
{% if page_obj.number|add:'3' < page_obj.paginator.num_pages %}
<li class="pagination__item">
<a class="pagination__link" href="?{{ genre }}{{ year }}page={{ page_obj.paginator.num_pages }}">
{{ page_obj.paginator.num_pages }}
</a>
</li>
{% endif %}
{% endif %}
</ul>
Thanks for any help
Your post_detail.html extends base.html, hence any content you wish to render must be inside some block and this block also must be present in the parent template (base.html here). You currently have some content outside any block and hence they aren't rendered. Put the HTML inside the block and it will show up:
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
<p>+ Edit Blog Post</p>
<p>+ Delete Blog Post</p>
<img src="{{ post.header_image.url|default_if_none:'fox.jpeg' }}">
{{ post.body|urlize }}
{% for comm in post.commentpost_set.all%}
{{ comm.user }} <br>
{{ comm.text }} <br><br>
{% endfor %}
<!-- put them inside the block -->
<br><br>
<hr>
<form method="post">
{% csrf_token %}
{{ comment_form.as_p }}
{% if request.user.is_authenticated %}
<input type="submit" value="Submit" class="btn btn-outline-success">
{% else %}
<input type="submit" value="Submit" class="btn btn-outline-success" disabled>
{% endif %}
</form>
<div class="main-comment-section">
{{ comments.count }} Comment{{ comments|pluralize }}
{% for comment in comments %}
<blockquote class="blockquote">
<p class="mb-0">{{ comment.content }}</p>
<footer class="blockquote-footer">by <cite title="Source Title">{{ comment.user|capfirst }}</cite></footer>
</blockquote>
{% endfor %}
</div>
{% endblock content %}

How to use django-summernote in templates

I have setup django-summernote on my project and everything is great, it works very good on admin , but i want to use it on my templates.
Note :
in django-summernote documentation they only explain how to use it if you have forms.py file but I dont
my main urls.py :
urlpatterns = [
path('games/', include('core.urls', namespace='core')),
path('summernote/', include('django_summernote.urls')),
]
my app(name=core) urls.py :
from django.urls import path
from . import views
app_name = 'core'
urlpatterns = [
path('new/', views.GameCreate.as_view(), name='game_new'),
path('<int:pk>/edit/', views.GameUpdate.as_view(), name='game_edit'),
]
my views.py :
class GameCreate(LoginRequiredMixin, CreateView):
model = Game
template_name = 'core/game_new.html'
fields = '__all__'
redirect_field_name = 'home'
class GameUpdate(LoginRequiredMixin, UpdateView):
model = Game
template_name = 'core/game_edit.html'
fields = '__all__'
my template file "game_new.html" :
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %} Add New Game {% endblock %}
{% block main %}
<section class="main-section">
<div class="container">
<h1>New Game</h1>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<input type='submit' value="Save" />
</form>
</div>
</section>
{% endblock %}
my template file "game_edit.html":
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %} Game Info {% endblock %}
{% block main %}
<section class="main-section"></section>
<div class="container">
<h1>Edit Game Info</h1>
<form action="" method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Update" />
</form>
</div>
</section>
{% endblock %}
my Models.py :
from django.db import models
from django.urls import reverse
# Create your models here.
class Game(models.Model):
name = models.CharField(max_length=140)
developer = models.CharField(max_length=140)
game_trailer = models.CharField(max_length=300, default="No Trailer")
game_story = models.TextField(default='No Story')
Firstly in your template dont forgate to add this:
{{ form.media }} <<<------ To load all js and css attached
In the document your models you must herit summernote widget. Example:
from django_summernote.widgets import SummernoteWidget, SummernoteInplaceWidget
class FormFromSomeModel(forms.ModelForm):
class Meta:
model = SomeModel
widgets = {
'foo': SummernoteWidget(),
'bar': SummernoteInplaceWidget(),
}

DeleteView doesn't delete and just refreshes the delete page

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.

Display form fields one at a time in template-django

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)

Python Django from does not work after refactoring

I have been working through the Tango With Django tutorial. However, I noticed that some of the examples did not adhere to what people consider Django best practices, so I went back to do a little refactoring. Here is how I first wrote a template for a form that allows a user to add a web page to a category.
<!DOCTYPE html>
<html>
{% extends 'rango/base.html' %}
{% block title %}Add a Page{% endblock %}
{% block body_block %}
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/category/{{ category_name }}/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"></input>
</form>
{%endblock%}
</html>
I then refactored the template like so:
<!DOCTYPE html>
<html>
{% extends 'rango/base.html' %}
{% block title %}Add a Page{% endblock %}
{% block body_block %}
<h1>Add a Page</h1>
<form id="page_form" method="post" action="{% url 'add_page' category_name %}"></form>
{% 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"></input>
</form>
{%endblock%}
</html>
However, now when I click the submit button, nothing happens. Here is the url pattern that I use:
url(r'^category/(?P<category_name_url>\w+)/add_page/$', views.add_page, name='add_page')
Here is my view:
#login_required
def add_page(request, category_name_url):
category_name = remove_underscores(category_name_url)
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
page = form.save(commit=False)
try:
cat = Category.objects.get(name=category_name)
page.category = cat
except Category.DoesNotExist:
return render(request, 'rango/add_page.html', {})
page.views = 0
page.save()
return category(request, category_name_url)
else:
print form.errors
else:
form = PageForm()
return render(request, 'rango/add_page.html',
{'category_name_url': category_name_url,
'category_name': category_name,
'form': form})
UPDATE:
Here is the code in 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_url>\w+)/$', views.category, name='category'),
url(r'^category/(?P<category_name_url>\w+)/add_page/$', views.add_page, name='add_page'),
url(r'^register/$', views.register, name='register'),
url(r'^login/$', views.user_login, name='login'),
url(r'^restricted/$', views.restricted, name='restricted'),
url(r'^logout/$', views.user_logout, name='logout'),
)
UPDATE:
I print out the result of {% url 'add_page' category_name %} and got /rango/category/Ruby/add_page/, which is the correct result. Looks like the url tag is resolving to the correct path. Still not sure why it is not working.
OMG! I feel so lame! This line was the issue:
<form id="page_form" method="post" action="{% url 'add_page' category_name %}"></form>
The fields and submit button were not enclosed in the form! Ugh!

Categories