Django - NoReverseMatch after simple changes in code - python

So,long story short,I started learning Django basics this week and followed a simple poll creating tutorial,which worked fine,but then I started trying to make a few changes to the code,and due to my inexperience in Django(and to be honest,also in HTML),I ended up getting this NoReverseMatch error. What I basically did was try to change the name of a class and it's uses in the app,and it's objects along the project(class TText).
Then the errors started showing up at both the /polls/* ( * being respective id number for a TText) and /polls/*/results in the localhost web page.
The first one gives the following error at detail.html,line 5:
Reverse for 'vote' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'polls/(?P<text_id>[0-9]+)/vote/$']
And the second at results.html,line 9:
Reverse for 'detail' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'polls/(?P<pk>[0-9]+)/$']
And here's my setup of this django app:
/mysite
urls.py
/polls
models.py
urls.py
views.py
/templates
/polls
detail.html
index.html
results.html
Where: /mysite/urls.py is:
from django.conf.urls import include,url
from django.contrib import admin
urlpatterns = [
url(r'^polls/', include('polls.urls')),
url(r'^admin/', admin.site.urls),
]
also - /polls/models.py :
from __future__ import unicode_literals
import datetime
from django.db import models
from django.utils import timezone
# Create your models here.
class TText(models.Model):
text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
text = models.ForeignKey(TText, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
also - /polls/urls.py :
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<text_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
also - /polls/views.py :
from django.shortcuts import get_object_or_404, render
# Create your views here.
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from .models import Choice, TText
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_text_list'
def get_queryset(self):
"""Return the last five published questions."""
return TText.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = TText
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = TText
template_name = 'polls/results.html'
def vote(request, text_id):
text = get_object_or_404(TText, pk=text_id)
try:
selected_choice = text.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'text': text,
'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=(text.id,)))
also - /polls/templates/polls/detail.html:
<h1>{{ text.text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' text.id %}" method="post">
{% csrf_token %}
{% for choice in text.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>
also: /polls/templates/polls/index.html :
{% if latest_text_list %}
<ul>
{% for text in latest_text_list %}
<li>{{ text.text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
also - /polls/templates/polls/results.html :
<h1>{{ text.text}}</h1>
<ul>
{% for choice in text.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
Vote again?
PS: It's the first time a post a question here on Stack,so feel free to point out any mistake on that as well.
OH,and yes, I did read the other posts of similar problems,but I coudn't match any of them with my own problem. Thank you for your time!

The context passed into generic views is based on the Model name. You have two options in the template, you can use either object or name_of_model. In your case, that's ttext. Alternatively, you can tell the generic view what to call the object in the context:
class DetailView(generic.DetailView):
model = TText
template_name = 'polls/detail.html'
context_object_name = 'text'
class ResultsView(generic.DetailView):
model = TText
template_name = 'polls/results.html'
context_object_name = 'text'
Then you can use what you're currently doing in your templates: text.id instead of ttext.id or object.id.

The problems are in your URL template tags. Essentially you are telling Django to find a URL that doesn't exist.
The main issue as far as I can see is that you are referring to a template variable text which doesn't exist. It doesn't exist because those templates are being rendered by Django's generic views, and the generic views use object as their standard template variable name for a single object. If you just change text to object in those template files you should get a better result.
The other option is to declare a context object name on the view class, like you've done in IndexView - context_object_name = 'latest_text_list'.

Related

How to add an extra context in a Class Based View (ListView)

I am trying to add another Context in a ListView so that it can be used in the same template but it is not working and it gets an error for
NoReverseMatch at /
Reverse for 'user-posts' with arguments '('',)' not found. 1 pattern(s) tried: ['score/user/(?P<username>[^/]+)$']
The 1st applied context is called Items model from a Core app, the 2nd context that I want to apply is the post model from score app
Here is the Views.py
class HomeView(ListView):
model = Item
paginate_by = 12
template_name = "home.html"
ordering = ['-timestamp']
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
try:
context['posts'] = Post.objects.all()
except Post.DoesNotExist:
context['posts'] = None
return context
Here is the models for Post
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
Here is the template which return the
NoReverseMatch at /
Reverse for 'user-posts' with arguments '('',)' not found. 1 pattern(s) tried: ['score/user/(?P[^/]+)$']
{% if posts %}
<a href="{% url 'score:user-posts' post.designer.username %}">
<button type="button" class="btn btn-success btn-sm btn-block">
Check my posts</button>
</a>
{% else %}
Show Nothing
{% endif %}
Here is the template which returns no errors but the if statement doesn't work
instead of using
{% url 'score:user-posts' post.designer.username %}
I used
{% url 'score:user-posts' item.designer.username %}
{% if posts %}
<a href="{% url 'score:user-posts' item.designer.username %}">
<button type="button" class="btn btn-success btn-sm btn-block">
Check my posts</button>
</a>
{% else %}
Show Nothing
{% endif %}
here is the URLs.py
app_name = 'core'
urlpatterns = [
path('', HomeView.as_view(), name='home'),
here is the score urls.py
app_name = 'score'
urlpatterns = [
path('', PostListView.as_view(), name='score'),
path('details/<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
path('new/', PostCreateView.as_view(), name='post-create'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
can you show your urls.py( + directory structure of your project)
i am not sure, but looks like you get wrong template file
But in your code you can change:
try:
context['posts'] = Post.objects.all()
except Post.DoesNotExist:
context['posts'] = None
you don't need try ... except... here. If you have empty table, Post.objects.all() will return empty queryset and you will never get your Exception
i think you need to add line in your urls.py
path('score/user/<slug:username>/', HomeView.as_view(), name="user-detail")
and then in your template you can use
{% url 'user-detail' item.designer.username %}

Django Tutorial: 'detail' is not a valid view function or pattern name

I am using Windows XP, Python 3.4 and Django 2.0.2
I am new to Django and am trying to follow the instructions in
https://docs.djangoproject.com/en/2.0/intro/tutorial04/
the Django tutorial. The most likely mistake that I made is that I did not cut
and paste code in the right places. It would be helpful to me (and possibly
others) if the writers of the tutorial had a reference to the complete list of
the py and html files at each stage (not just part of the code).
I have the following error:
http://127.0.0.1:8000/polls/
`
NoReverseMatch at /polls/
Reverse for 'detail' not found. 'detail' is not a valid view function or pattern name.
Request Method: GET
Request URL: http://127.0.0.1:8000/polls/
Django Version: 2.0.2
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'detail' not found. 'detail' is not a valid view function or pattern name.
Exception Location: C:\programs\python34\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 632
Python Executable: C:\programs\python34\python.exe
Python Version: 3.4.3
Python Path:
['Y:\mysite\mysite',
'C:\WINDOWS\system32\python34.zip',
'C:\programs\python34\DLLs',
'C:\programs\python34\lib',
'C:\programs\python34',
'C:\programs\python34\lib\site-packages']
Server time: Thu, 6 Dec 2018 15:35:56 -0600
Error during template rendering
In template Y:\mysite\mysite\polls\templates\polls\index.html, error at line 4
Reverse for 'detail' not found. 'detail' is not a valid view function or pattern name.
1 {% if latest_question_list %}
2 <ul>
3 {% for question in latest_question_list %}
4 <li>{{ question.question_text }}</li>
5 {% endfor %}
6 </ul>
7 {% else %}
8 <p>No polls are available.</p>
9 {% endif %}
`
The end of the error stream read
raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'detail' not found. 'detail'
is not a valid view function or pattern name.
[06/Dec/2018 15:35:57] "GET /polls/ HTTP/1.1" 500 127035
Not Found: /favicon.ico
[06/Dec/2018 15:35:58] "GET /favicon.ico HTTP/1.1" 404 2078
Following the tutorial, I have the following files:
Y:\mysite\mysite\polls\models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
Y:\mysite\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'),
]
Y:\mysite\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 .models import Question
from django.views import generic
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."""
return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
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)
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.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,))
Y:\mysite\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>
Y:\mysite\mysite\polls\templates\polls\index.html
`
{% 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 %}
`
Y:\mysite\mysite\polls\templates\polls\results.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?
CAN ANYONE TELL ME WHAT I AM DOING WRONG?
All my HTML and PY files were cut and pasted from the
Django Tutorial.
If someone suggests a change in either an HTML of PY file, it would be very
helpful if that person list the complete modified files (not just the
changes).
Thanks!!
instead of
<li>{{ question.question_text }}</li>
Use
<li>{{ question.question_text }}</li>
Because the polls app's urls are included in urlpatterns in the urls.py(which resides ins same folder as settings.py) with name polls like this:
urlpatterns = [
...
path('', include('polls.url', name='polls')
]

Why won't my server start running?

Why am I getting an error when trying to run my server to access the database to see if my code works? While in my projects folder in Terminal, I ran sudo python manage.py runserver to try to run the server but it doesn't work because of the aforementioned error. I've looked around SO but can't find one directly related to my problem.
I'm guessing my if() statement is the problem.
The error I'm getting says:
RuntimeError: maximum recursion depth exceeded while calling a Python object
Here's my views.py file:
from .models import Album
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.core.urlresolvers import reverse_lazy
from django.views import generic
from django.views.generic import View
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import UserForm
class IndexView(generic.ListView):
template_name = 'music/index.html'
context_object_name = 'all_albums'
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DeleteView):
model = Album
template_name = 'music/detail.html'
class AlbumCreate(CreateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class AlbumUpdate(UpdateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class AlbumDelete(DeleteView):
model = Album
success_url = reverse_lazy('music:index')
class UserFormView(View):
form_class = UserForm
template_name = 'music/registration_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
#cleaned normalized data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
Here's the error:
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 255, in check
warnings.extend(check_resolver(pattern))
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/core/checks/urls.py", line 26, in check_resolver
return check_method()
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 172, in check
warnings = self._check_pattern_startswith_slash()
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 140, in _check_pattern_startswith_slash
regex_pattern = self.regex.pattern
Here's my forms.py file:
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm): # UserForm inherits from forms.
passwords = forms.CharField(widget=forms.PasswordInput)
class Meta: # Information about your class.
model = User # whenevr a creates sign up to your site it's gonna go in same table
fields = ['username', 'email', 'password']
Here's my urls.py file:
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
app_name = 'music'
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^music/', include('music.urls'))
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.MEDIA_ROOT)
Here's my album_form.html file:
{% extends 'music/base.html' %}
{% block title %}Add a New Album{% endblock %}
{% block album_active %}active{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<form class="horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'music/form-template.html' %}
<div class="form-group">
<div class="col-sum-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Here's my index.html file:
{# loads path to static file #}
{% extends 'music/base.html' %}
{% block body %}
<ul>
{% for album in all_albums %}
<li>{{ album.album_title }}</li>
{% endfor %}
</ul>
{% endblock %}
I suspect you have a recursive reference from your include in music.urls to urls.py since the error that django throws is specific to URL resolver.
Your if statement has no error. 'music:index' refers to namespaced url names and still need named url statements in urls.py. Since in simple projects, there is only one application, the namespace is redundant. So in most cases, 'index' should be used instead, just like what I have show below.
In your urls.py, there is a include to music.urls, and it seems to be recursive reference to itself. 'music.urls' refers to the file urls.py in music directory.
If you do not have a valid python object for 'music.urls', then your include statement is wrong.
I do not use include urls in my project, so there will need to be a statement for each view defined in views.py. To test whether your server starts correctly, I would try the following urlpatterns. Don't forget to import IndexView and DetailView. Add more url statements for you other views after testing out 1 or 2 first.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^music/index/$', IndexView.as_view() , name='Index'),
url(r'^music/detail/(?P<pk>[0-9]+)/$', DetailView.as_view() , name='Detail'),
]
I use named url, and the statement in index.html should be written as follows:
{{ album.album_title }}
The namespace 'music:' is omitted since it is implicit and will look simpler. You should leave it out for simple applications as it may be confusing for beginners.

Django Generic Views :How does DetailView automatically provides the variable to the template ??

In the following code, How does the template details.html knows that album is passed to it by views.py although we have never returned or defined any context_object_name in DetailsView class in views.py.
Please explain how are the various things getting connected here.
details.html
{% extends 'music/base.html' %}
{% block title %}AlbumDetails{% endblock %}
{% block body %}
<img src="{{ album.album_logo }}" style="width: 250px;">
<h1>{{ album.album_title }}</h1>
<h3>{{ album.artist }}</h3>
{% for song in album.song_set.all %}
{{ song.song_title }}
{% if song.is_favourite %}
<img src="http://i.imgur.com/b9b13Rd.png" />
{% endif %}
<br>
{% endfor %}
{% endblock %}
views.py
from django.views import generic
from .models import Album
class IndexView(generic.ListView):
template_name = 'music/index.html'
context_object_name = 'album_list'
def get_queryset(self):
return Album.objects.all()
class DetailsView(generic.DetailView):
model = Album
template_name = 'music/details.html'
urls.py
from django.conf.urls import url
from . import views
app_name = 'music'
urlpatterns = [
# /music/
url(r'^$', views.IndexView.as_view(), name='index'),
# /music/album_id/
url(r'^(?P<pk>[0-9]+)/$', views.DetailsView.as_view(), name='details'),
]
Thanks in advance !!
If you check the implementation of get_context_name(), you'll see this:
def get_context_object_name(self, obj):
"""
Get the name to use for the object.
"""
if self.context_object_name:
return self.context_object_name
elif isinstance(obj, models.Model):
return obj._meta.model_name
else:
return None
And the implementation for get_context_data() (from SingleObjectMixin):
def get_context_data(self, **kwargs):
"""
Insert the single object into the context dict.
"""
context = {}
if self.object:
context['object'] = self.object
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
context[context_object_name] = self.object
context.update(kwargs)
return super(SingleObjectMixin, self).get_context_data(**context)
So you can see that get_context_data() adds to the dictionary an entry with the key context_object_name (from get_context_object_name()) which returns obj._meta.model_name when self.context_object_name isn't defined. In this case, the view got self.object as a consequence of the call to get() which calls get_object(). get_object() takes the model that you've defined and automatically queries it from your database using the pk you've defined in your urls.py file.
http://ccbv.co.uk/ is a very good website for seeing all of the functions and attributes the class based views of Django has to offer in a single page.
This can be helpful where if context_object_name is not set, the context name will be constructed from the model_name of the model that the queryset is composed from
https://docs.djangoproject.com/en/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_object_name

Defining Views and URLs for Many to Many field in Django

I'm new to Django and have been stuck on this for a few days now. Hoping to find some help here. I've searched stackoverflow and read through the django docs but haven't been able to grasp this. I'm using Django 1.6.2 and Python 2.7.
I'm setting up a simple news app in which article has a ManyToMany relationship with category. I'm running into trouble trying to display articles from a specific category. I have the index working displaying all articles and also the single page view is working e.g. clicking on article title from index brings you to the article itself. Once in the article I am displaying the article category. Up to here all is well. When I try to link the category and display an index for all posts in that category I get a NoReverseMatch for the url 'category-archive'.
Should I do this in a view like I'm trying or would the Manager work better? Open to all suggestions and answers. Like I said I'm new so would like to know best practice. Here is my code and thank you in advance for dealing with a noobie.
models.py
from django.db import models
from tinymce import models as tinymce_models
class ArticleManager(models.Manager):
def all(self):
return super(ArticleManager, self).filter(active=True)
class Category(models.Model):
title = models.CharField(max_length=65)
slug = models.SlugField()
def __unicode__(self, ):
return self.title
class Article(models.Model):
title = models.CharField(max_length=65)
slug = models.SlugField()
description = models.CharField(max_length=165)
content = tinymce_models.HTMLField()
categories = models.ManyToManyField(Category)
image = models.ImageField(upload_to='article/images')
active = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
objects = ArticleManager()
def __unicode__(self, ):
return self.title
class Meta:
ordering = ['-timestamp',]
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, RequestContext, get_object_or_404
from .models import Article, Category
def all_articles(request):
articles = Article.objects.all()
return render_to_response('news/all.html', locals(), context_instance=RequestContext(request))
def single_article(request, slug):
article = get_object_or_404(Article, slug=slug)
return render_to_response('news/single.html', locals(), context_instance=RequestContext(request))
def category_archive(request, slug):
articles = Article.objects.filter(category=category)
categories = Category.objects.all()
category = get_object_or_404(Category, slug=slug)
return render_to_response('news/category.html', locals(), context_instance=RequestContext(request))
single.html - for single article view
{% extends 'base.html' %}
{% block content %}
<h1>{{ article.title }}</h1>
<img src='{{ MEDIA_URL }}{{ article.image }}' class="article-image img-responsive"/>
<p>{{ article.content|safe }}</p>
<p class='small'>
**this next line gets an error for the url 'category-archive'**
{% for category in article.categories.all %}Category: <a href='{% url "category-archive" %}{{ category.slug }}'>{{ category }}</a>{% endfor %}</p>
{% endblock %}
category.html - display all articles in specific category
{% extends 'base.html' %}
{% block content %}
{% for article in articles %}
<h1><a href='{% url "articles" %}{{ article.slug }}'>{{ article }}</a></h1>
<a href='{% url "articles" %}{{ article.slug }}'><img src='{{ MEDIA_URL }}{{ article.image }}' class="img-responsive"/></a>
{{ article.description }}
{% if forloop.counter|divisibleby:4 %}
<hr/>
<div class='row'>
{% endif %}
{% endfor %}
</div>
{% endblock %}
urls.py - project urls
from django.conf.urls import patterns, include, url
from django.conf import settings
from filebrowser.sites import site
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^tinymce/', include('tinymce.urls')),
(r'^admin/filebrowser/', include(site.urls)),
(r'^grappelli/', include('grappelli.urls')),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',{
'document_root': settings.STATIC_ROOT
}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve',{
'document_root': settings.MEDIA_ROOT
}),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'dl.views.home', name='home'),
(r'^news/', include('news.urls')),
(r'^guides/', include('guides.urls')),
)
urls.py - news urls
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('news.views',
url(r'^$', 'all_articles', name='articles'),
url(r'^(?P<slug>[-\w]+)/$', 'single_article'),
**This next one is giving me the problem I suspect - should be url to category with articles**
url(r'^chive/(?P<slug>[-\w]+)/?', 'category_archive', name='category-archive'),
)
I would have post it as a comment but i don't have the reputation.
I think that the thing is that the URL Dispatcher expects the category-archive to also get the slug. so you should change the URL in the template to:
{% url "category-archive" category.slug %}
hope this helps!

Categories