Django Polls Project: Reverse for 'polls.index' not found - python

I'm trying to finish my Django Polls Project from the Django Documentation but I ran into the "Reverse for 'polls.index' not found. 'polls.index' is not a valid view function or pattern name." error.
The full error details can be seen here
The following are my files.
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<title>Pollster {% block title %}{% endblock %}</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 m-auto">
{% block content %}{% endblock %}
</div>
</div>
</div>
</body>
</html>
index.html
{% extends 'base.html' %}
{% block content %}
<h1 class="text-center mb-3">Poll Questions</h1>
{% if latest_question_list %}
{% for question in latest_question_list %}
<div class="card mb-3">
<div class="card-body">
<p class="lead">{{ question.question_text}}</p>
Vote Now
Results
</div>
</div>
{% endfor %}
{% else %}
<p>No polls available</p>
{% endif %}
{% endblock %}
mysite.urls
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
polls.urls
from django.urls import path
from . import views #from ALL import views
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('<int:question_id>/results/', views.results, name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
polls.views
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from .models import Question, Choice
# Get questions and display them
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
# Show specific question and choices
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
# Get question and display results
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
# Vote for a question choice
def vote(request, question_id):
# print (request.POST['choice'])
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
detail.html
{% extends 'base.html' %}
{% block content %}
Back To Polls
<h1 class="text-center mb-3">{{ question.question_text }}</h1>
{% if error_message %}
<p class="alert alert-danger">
<strong>{{ error_message }}</strong>
</p>
{% endif %}
<form action="{% url 'polls:vote' question.id %}" method ="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<div class="form-check">
<input type="radio" name="choice" class="form-check-input" id="choice{{ forloop.counter }}" value = "{{ choice.id }}"/>
<label for="choice{{ forloop.counter }}">
{{ choice.choice_text }}
</label>
</div>
{% endfor %}
<input type="submit" value ="Vote" class ="btn btn-success btn-lg btn-block mt-4" />
</form>
{% endblock %}
I am new to Django and I would like to learn methods to find out where the errors could be originating from. I checked the code in reference with this finished project from the channel I'm watching but couldn't find the error I made.
Where could the error in my code be?
I researched and this stackoverflow question might be the same as mine but was not solved as well.
Here is my folder structure
I am also new to python for web development so any tips on how I could study this would be helpful. Thank you in advanced!

Related

Django Polls Tutorial No answer detected in choice.votes polls

I decided to learn Django and started with the 'Django Polls App' which I figured would be the most simple, I am gripping the idea of how it works but I am stuck. To learn a bit better, I changed the variables and names from the original docs to my own.
Example : question_text = q_text, Choice = Choices, choice_text = choice.. etc.
Now I can't figure out what's wrong with my code as I can't make the polls work. There is no error code but it simply doesn't display the number of votes or show a success sign. I was also following Traversy Media's Django Crash Course (Polls App).
My code :
views.py
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.template import loader
from .models import Question, Choices
def index(request):
latest_ques = Question.objects.order_by('-published')[:5]
context = {'latest_ques': latest_ques}
return render(request, 'polls/index.html', context)
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choices_set.get(pk=request.POST['choices'])
except (KeyError, Choices.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
models.py
from django.db import models
class Question(models.Model):
q_text = models.CharField(max_length=200)
published = models.DateTimeField('date published')
def __str__(self):
return self.q_text
class Choices(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice
details.html
{% extends 'base.html' %}
{% block content %}
<a class="btn btn-secondary btn-sm mb-3" href="{% url 'polls:index' %}">Back To Polls</a>
<h1 class="text-center mb-3">{{ question.q_text }}</h1>
{% if error_message %}
<p class="alert alert-danger">
<strong>{{ error_message }}</strong>
</p>
{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choices in question.choices_set.all %}
<div class="form-check">
<input type="radio"
name="choices"
class="form-check-input"
id="choices{{ forloop.counter }}"
value="{{ choices.id }}">
<label for="choices{{ forloop.counter }}">{{ choices.choice }}</label>
</div>
{% endfor %}
<input type="submit" value="Vote" class="btn btn-success btn-lg btn-block mt-4" />
</form>
{% endblock %}
results.html
{% extends 'base.html' %}
{% block content %}
<h1 class="mb-5 text-center">{{ question.q_text }}</h1>
<ul class="list-group mb-5">
{% for choices in question.choices_set.all %}
<li class="list-group-item">
{{ choices.choice }} <span class="badge badge-success float-right">{{ choices.votes }} vote{{ choices.votes | pluralize }}</span>
</li>
{% endfor %}
</ul>
<a class="btn btn-secondary" href="{% url 'polls:index' %}">Back To Polls</a>
<a class="btn btn-dark" href="{% url 'polls:detail' question.id %}">Vote Again?</a>
{% endblock %}
urls.py
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('<int:question_id>/results/', views.results, name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
I've been on the internet for hours and can't figure it out. Not getting a proper answer. Thought I'd try my luck here.
I've tried to change the names of multiple variables, I've had many errors throughout but this one I can't figure out. The solution would actually be quite simple I know it but can't really put a finger on it. Thanks.
Nevermind, I found out that there were some misspelled variables. It worked after I went line by line to find the error.

Making search bar in django

Im trying to make a search bar in django and watched several youtube totorials and none of those worked. What im trying to do is either make a search bar that redirects to articles/what_you_searched_for or if not possible show up results that include search. If someone has enough time they can tell me how to do both :).
in views.py:
def index(request):
queryset = article.objects.all()
number_of_records = article.objects.count()
random_page = random.randint(1,number_of_records)
context = {
"object_list": queryset,
"random_page": random_page
}
# query = ""
# if request.GET:
# query = request.GET['q']
# context['query'] = str(query)
entries = util.list_entries()
return render(request, "encyclopedia/index.html", context)
#{
#"entries": util.list_entries(),
#"random_page": random_page,
#})
def dynamic_articles_view(request, my_id):
obj = article.objects.get(id= my_id)
number_of_records = article.objects.count()
random_page = random.randint(1,number_of_records)
context = {
"object": obj,
"random_page": random_page
}
return render(request, "encyclopedia/article_detail.html", context)
in index.html:
{% extends "encyclopedia/layout.html" %}
{% block title %}
Encyclopedia
{% endblock %}
{% block body %}
<h1 id="demo" onclick="add_article()">Article</h1>
<ul>
{% for instance in object_list %}
<li>{{instance.title}}</li>
{% endfor %}
</ul>
{% endblock %}
layout.html: ------------ SEARCH BAR HERE ---------
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link href="{% static 'encyclopedia/styles.css' %}" rel="stylesheet">
</head>
<body>
<div class="row">
<div class="sidebar col-lg-2 col-md-3">
<h2>Wiki</h2>
<form action = "/articles/{{q}}"> __________EXACTLY HERE ________
<input class="search" type="text" name="q" placeholder="Search...">
</form>
<div>
Home
</div>
<div>
<a href = "/new_article" >Create New Article</a>
</div>
<div>
Random Page
</div>
{% block nav %}
{% endblock %}
</div>
<div class="main col-lg-10 col-md-9">
{% block body %}
{% endblock %}
</div>
</div>
</body>
</html>
urls:
from django.contrib import admin
from django.urls import include, path
from encyclopedia import views
from encyclopedia.views import index, new_article, dynamic_articles_view
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("encyclopedia.urls")),
path('new_article/', new_article),
path('home/', index, name = 'home'),
path('articles/<int:my_id>/', dynamic_articles_view, name = 'articless')
]
encyclopedia urls (other folder):
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("", views.new_article, name="new_article")
]
if needed i will comment models and forms but i dont want to make my question to long.
Simplest way is to add a GET form in your template with a search input without setting the action of the form:
<form action="">
<input type="text" name="search" placeholder="Search by title" value="{{request.GET.title}}">
<input type="submit" value="Search">
</form>
Then in the views.py in the you get the value. If it's given, you filter by it:
def dynamic_articles_view(request):
context['object_list'] = article.objects.filter(title__icontains=request.GET.get('search'))
return render(request, "encyclopedia/article_detail.html", context)

NoReverseMatch at - django polls app tutorial

I keep getting this when trying to load da page:
NoReverseMatch at /polls/
Reverse for 'vote' with arguments '('',)' not found. 1 pattern(s) tried: ['polls/(?P<question_id>[0-9]+)/vote/$']
In template C:\Users\sarah\Desktop\django2\myproject\my_site\polls\templates\polls\index.html, error at line 20
line 20:
<form action="{% url 'polls:vote' question.id %}" method="post">
I am a complete beginner at django, css, html, ... I kept checking in with the tutorial, comparing my code with the code reference in the tutorial, however I see no mistake.
My index.html:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>
The vote function in views.py:
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
urls.py:
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
Thank you.
The main reason here is you are using your index.html with the form where you should really have this in polls/detail where you have access to a question object by pk. Right now you are trying to access the id property of question but question is undefined in your index.html.
Place the following in your polls/details.html
<h1>{{ question.question_text }}</h1>
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>
Then, navigate to polls/1 or whatever question.id you want and then try and use the form.

Why do I have this error in Django?

I'm following the Django tutorial process, currently located on part 6.
I get an error when I click on the list from my web page. I looked up where the problem occurred, but I could not find it.
This is the message from a web browser:
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/polls/1//
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
polls/ [name='index']
polls/ <int:pk>/ [name='detail']
polls/ <int:pk>/results/ [name='results']
polls/ <int:question_id>/vote/ [name='vote']
admin/
The current path, polls/1//, didn't match any of these.
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
traceback
"GET /polls/1// HTTP/1.1" 404 2703
mysite/polls/views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from django.utils import timezone
from .models import Choice, Question
# ...
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Question.objects.filter(pub_date__lte=timezone.now())
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
mysite/polls/urls.py
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
mysite/polls/templates/polls/index.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
mysite/polls/templates/polls/detail.html
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
mysite/polls/templates/polls/result.html
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
Vote again?
You have two slashes ('//') at the end of your url, this should be just one:
http://localhost:8000/polls/1/
More specifically, in your polls/index.html template, you have the following line:
<li>{{ question.question_text }}</li>
Of that line, this part generates the url for you:
{% url 'polls:detail' question.id %}
that becomes:
http://localhost:8000/polls/1/
But you have added an extra slash behind it, look at the end of the below string:
"{% url 'polls:detail' question.id %}/"
Remove that, and I think your code should work.

Django2.0 “remove hardcoded urls in templates” not working

I'm checking out django for the first time following the tutorial
[https://docs.djangoproject.com/en/2.0/intro/tutorial03/]
When I change the hardcoded url from:
<li>{{ question.question_text }}</li>
to:
<li>{{ poll.question }}</li>
I get a error as follow:
My urls.py files are:
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
# ex:/polls/5/
path('<int:question_id>/', views.detail, name='datail'),
# ex: /polls/5/results/
path('<int:question_id>/vote/', views.vote, name='vote'),
# ex: /polls/vote/
path('<int:question_id>/results/', views.results, name='results'),
]
My views.py files are:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Question,Choice
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question':question})
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question':question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form
return render(request, 'polls/detail.html',{
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes +=1
selected_choice.save()
# Always return an HttpRespinsedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list':latest_question_list}
return render(request, 'polls/index.html', context)
My index.html fils are:
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
my details.html fils are:
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
So, I am confused of Removing hardcoded URLs in templates does not work.
Could someone help me? Thanks a lot!
You should be using name spacing in your urls. That is why you set the app_name to polls. Your url should look like this,
<li>{{ question.question_text }}</li>
Right now your url conf doesn't know what detail your talking about.
Here is the url conf docs and name spacing is talked about at the bottom.
https://docs.djangoproject.com/en/2.0/topics/http/urls/

Categories

Resources