Question

I'm in the process of learning Django and currently I'm on a project following the Polls Tutorial loosely.

Now I'm trying to convert to generic views and this is where I'm running into problems:

news/models.py

[...]
class News(models.Model):
  id = models.IntegerField(primary_key=True, editable=False)
  category = models.CharField(max_length=50L)
  title = models.CharField(max_length=200L)
  #rss_summary = models.CharField(max_length=2000L)
  rss_summary = models.TextField(max_length=2000L)
  #body_text = models.CharField(max_length=5000L)
  body_text = models.TextField(max_length=5000L)
  post_date = models.DateTimeField()
  class Meta:
      db_table = 'news'
  def __unicode__(self):
      return self.title

news/urls.py

from django.conf.urls import patterns, url, include
from django.views.generic import DetailView, ListView

from news import views
from news.models import News

urlpatterns = patterns('',
    url(r'^$',
        ListView.as_view(
            queryset=News.objects.order_by('-post_date'),
            context_object_name='allnews',
            template_name='news/news.html'),
        name='news_index'),
[...]

news/templates/news/news.html

[...]
{% for item in allnews %}
  <h1 class="news"><a href="{% url 'news_index' item.id %}">{{item.title}}</a></h1>
  [...]
{% endfor %}

Now my problem: I'd like to link to a specific news item (via ID) using the {% url 'foo' id %} syntax using generic views like ListView or DetailView. How can I achieve this? I declared a name for the ListView, but I'm unable to figure out how to to specify the allnews.id.

With the code above I get the error

NoReverseMatch at /news/ Reverse for 'news_index' with arguments '(7L,)' and keyword arguments '{}' not found.

The funny thing is, "7L" is the id of the latest news item...

Was it helpful?

Solution

You should have 2 views, one for the list and another for the details, so when you click on the item link in the list page, it will take you to the details view and template:

news/urls.py

from django.conf.urls import patterns, url, include
from django.views.generic import DetailView, ListView

from news import views
from news.models import News

urlpatterns = patterns('',
    url(r'^$',
        ListView.as_view(
            queryset=News.objects.order_by('-post_date'),
            context_object_name='allnews',
            template_name='news/news.html'),
        name='news_index'),

    url(r'^(?P<id>\d+)/$',
        DetailView.as_view(
            model=News,
            context_object_name='item',
            template_name='news/news_item.html'),
        name='news_detail'),
[...]

news/templates/news/news.html

[...]
{% for item in allnews %}
  <h1 class="news"><a href="{% url 'news_detail' item.id %}">{{item.title}}</a></h1>
  [...]
{% endfor %}

news/templates/news/news_item.html

<a href="{% url 'news_index' %}">Back</a>

<h1 class="news">{{item.title}}</h1>
<p>{{ item.body_text }}</p>

OTHER TIPS

You are using a wrong view for details. You defined news_index is a ListView, you need to implement DetailView. See more for Urls in generic views in django docs.

url(r'^(?P<id>\d+)/$',
        DetailView.as_view(
            model=News,
            template_name='news/detail.html'),
        name='news_detail'),

and then in template

{% for item in allnews %}
  <h1 class="news"><a href="{% url 'news_detail' item.id %}">{{item.title}}</a></h1>
  [...]
{% endfor %}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top