在Django中为多对多字段定义视图和URL

0 投票
1 回答
1074 浏览
提问于 2025-04-17 21:25

我刚开始学习Django,已经在这个问题上卡了好几天了。希望能在这里找到一些帮助。我在StackOverflow上搜索过,也看过Django的文档,但还是没搞明白。我使用的是Django 1.6.2和Python 2.7。

我正在搭建一个简单的新闻应用,其中文章分类之间有一个多对多的关系。我在尝试显示特定分类的文章时遇到了麻烦。我已经把首页设置好了,可以显示所有文章,单篇文章的页面也能正常工作,比如从首页点击文章标题可以进入到文章本身。在文章页面中,我显示了文章的分类。到这里一切都很好。但是当我尝试链接分类并显示该分类下所有文章的列表时,我遇到了一个NoReverseMatch的错误,提示找不到'category-archive'这个网址。

我应该像现在这样在视图中处理这个问题,还是用Manager会更好呢?我欢迎所有建议和答案。正如我所说,我是新手,所以想知道最佳实践是什么。以下是我的代码,提前感谢你们对新手的耐心。

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 - 单篇文章的视图

{% 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 - 显示特定分类下的所有文章

{% 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 - 项目的网址配置

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 - 新闻的网址配置

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'),

)

1 个回答

4

我本来想把这个作为评论发出去,但我没有足够的声望。
我觉得问题在于,URL调度器希望类别归档也能接收到slug(网址的一部分)。所以你应该把模板中的网址改成:

{% url "category-archive" category.slug %}

希望这能帮到你!

撰写回答