4

現在、Django の学習を進めていますが、この問題を自分で解決する方法がわかりません。私は本Developers Library - Python Web Development With Djangoを読んでいます.1つの章で、2つのモデル(ストーリーとカテゴリ)、いくつかの汎用ビューとカスタムビュー、ビューのテンプレートを備えた単純なCMSシステムを構築しています。

この本には、ストーリー、ストーリーの詳細、および検索を一覧表示するためのコードのみが含まれています。それを拡張して、カテゴリとストーリーのネストされたリストを含むページを作成したいと考えました。

- Category1
-- Story1
-- Story2
- Category2
- Story3 etc.

カテゴリのリストに独自の一般的な object_list ビューを追加する方法を理解することができました。私の問題は、ストーリーが公開されているかどうかにかかわらず、ストーリーモデルに STATUS_CHOICES があり、デフォルトで公開ストーリーのみを取得するカスタムマネージャーがあることです。一般的なカテゴリ リスト ビューに、カスタム マネージャーも使用し、パブリック ストーリーのみをフェッチするように指示する方法がわかりません。その小さな問題を除いて、すべてが機能します。1 つのページでそのカテゴリのすべてのストーリーのサブ リストを含むすべてのカテゴリのリストを作成できます。唯一の問題は、リストに非公開のストーリーが含まれていることです。

ここで正しい軌道に乗っているかどうかはわかりません。私のurls.pyには、すべてのCategoryオブジェクトを取得する汎用ビューが含まれており、私のテンプレートでは、category.story_set.allを使用して、そのカテゴリのすべてのStoryオブジェクトを取得し、ループします。

テンプレートに if ステートメントを追加し、モデル ファイルの VIEWABLE_STATUS を使用して、リストするかどうかを確認することは可能だと思います。このソリューションの問題点は、DRY との互換性があまりないことです。

カテゴリで story_set を使用するときにパブリック Story オブジェクトでのみ取得するカテゴリ モデルのマネージャーを追加することは可能ですか?

それとも、これは私の問題を攻撃する間違った方法ですか?

関連コード

urls.py (カテゴリ リスト ビューのみ):

urlpatterns += patterns('django.views.generic.list_detail',
    url(r'^categories/$', 'object_list', {'queryset': Category.objects.all(),
                                          'template_object_name': 'category'
                                         }, name='cms-categories'),

models.py:

from markdown import markdown
import datetime
from django.db import models
from django.db.models import permalink
from django.contrib.auth.models import User

VIEWABLE_STATUS = [3, 4]

class ViewableManager(models.Manager):
    def get_query_set(self):
        default_queryset = super(ViewableManager, self).get_query_set()
        return default_queryset.filter(status__in=VIEWABLE_STATUS)

class Category(models.Model):
    """A content category"""
    label = models.CharField(blank=True, max_length=50)
    slug = models.SlugField()

    class Meta:
        verbose_name_plural = "categories"

    def __unicode__(self):
        return self.label

    @permalink
    def get_absolute_url(self):
        return ('cms-category', (), {'slug': self.slug})

class Story(models.Model):
    """A hunk of content for our site, generally corresponding to a page"""

    STATUS_CHOICES = (
        (1, "Needs Edit"),
        (2, "Needs Approval"),
        (3, "Published"),
        (4, "Archived"),
    )

    title = models.CharField(max_length=100)
    slug = models.SlugField()
    category = models.ForeignKey(Category)
    markdown_content = models.TextField()
    html_content = models.TextField(editable=False)
    owner = models.ForeignKey(User)
    status = models.IntegerField(choices=STATUS_CHOICES, default=1)
    created = models.DateTimeField(default=datetime.datetime.now)
    modified = models.DateTimeField(default=datetime.datetime.now)

    class Meta:
        ordering = ['modified']
        verbose_name_plural = "stories"

    def __unicode__(self):
        return self.title

    @permalink
    def get_absolute_url(self):
        return ("cms-story", (), {'slug': self.slug})

    def save(self):
        self.html_content = markdown(self.markdown_content)
        self.modified = datetime.datetime.now()
        super(Story, self).save()

    admin_objects = models.Manager()
    objects = ViewableManager()

category_list.html (関連テンプレート):

{% extends "cms/base.html" %}
{% block content %}
    <h1>Categories</h1>
    {% if category_list %}
        <ul id="category-list">
        {% for category in category_list %}
            <li><a href="{{ category.get_absolute_url }}">{{ category.label }}</a></li>
            {% if category.story_set %}
                <ul>
                    {% for story in category.story_set.all %}
                        <li><a href="{{ story.get_absolute_url }}">{{ story.title }}</a></li>
                    {% endfor %}
                </ul>
            {% endif %}
        {% endfor %}
        </ul>
    {% else %}
        <p>
            Sorry, no categories at the moment.
        </p>
    {% endif %}
{% endblock %}
4

4 に答える 4

11

ドキュメントは少し不明瞭ですが、属性が探しているものかもしれません。試しているときは、この機能が を使用していることに注意してください。これは、与えられた属性名に関係なく、Model クラスで宣言された最初の Manager を常に指します。代わりに適切なクラスでメソッドをオーバーライドすることにより、管理サイトで編集可能なアイテムをいつでもカスタマイズできます。use_for_related_fields Manager_default_managerquerysetModelAdmin

それに失敗して...

class Category(models.Model):
    def public_stories(self):
        return Story.objects.filter(category=self)

...と...

{% for story in category.public_stories %}

これにより、少なくとも、どのストーリーを表示できるかを決定するロジックの重複を回避できます。

于 2009-02-19T15:08:48.863 に答える
4

テンプレート固有のソリューションが必要な場合は、カスタムフィルターを作成できます。このようにして、モデルクラスに触れないようにすることができます

これがフィルターになります。

from django import template

register = template.Library()

@register.filter
def viewable(queryset):
    return queryset.filter(status__in=VIEWABLE_STATUS)

そして、あなたはそれをあなたのテンプレートで使うことができます

{% category.story_set|viewable %}
于 2009-10-10T18:29:44.877 に答える
2

@insin の回答を詳しく説明するuse_for_related_fields = Trueには、ViewableManagerクラスに追加する必要があります。そうすれば、必要なメソッドCategory.story_setを持つカスタム マネージャーのインスタンスが返されます。get_query_setテンプレートタグは次のようになります

{% category.story_set.get_query_set %}

編集:@insinの答えははるかに優れています。それを使用します。

于 2009-02-19T15:21:12.910 に答える