Django经理为_set in model [英] Django manager for _set in model

查看:94
本文介绍了Django经理为_set in model的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在学习Django,但我无法想像如何解决这个问题。我正在阅读书籍开发人员库 - 使用Django的Python Web开发,并且在一章中,您将使用两个模型(故事和类别)构建一个简单的CMS系统,一些通用视图和自定义视图以及视图。



本书仅包含列出故事,故事细节和搜索的代码。我想扩展它,并为类别和故事构建一个带有嵌套列表的页面。

   - 类别1 
- Story1
- Story2
- Category2
- Story3等

我设法找出如何添加我自己的通用object_list视图为类别列表。我的问题是,如果故事是公开的,故事模式有STATUS_CHOICES,而且每个默认情况下只能获取公共故事的自定义管理员。我无法弄清楚如何告诉我的通用类别列表视图,也可以使用自定义管理器,并且仅获取公共故事。一切工作除了小问题。我可以在一个页面上为所有类别创建列表,其中包含该类别中所有故事的子列表,唯一的问题是该列表包含非公开故事。



我不知道我是否在正确的轨道上。我的urls.py包含一个通用视图,它提取所有的Category对象,在我的模板中,我使用 category.story_set.all 获取该类别的所有Story对象,然后循环。 / p>

我认为可以在模板中添加一个if语句,并使用我的模型文件中的VIEWABLE_STATUS来检查是否应该被列出。该解决方案的问题是它的DRY不兼容。



是否可以为类别模型添加某种管理器,只能在公共Story对象中获取在某个类别上使用story_set?



或者是错误的方式来攻击我的问题?



相关代码



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:

 从markdown import markdown 
import datetime
从django.db导入模型
从django.db.models导入永久链接
从django.contrib.auth.models导入用户

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)

类别(models.Model):
内容类别
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):
我们网站的一大堆内容,一般对应一个页面

STATUS_CHOICES =(
(1,需要编辑),
(2,需要批准),
(3, 发布),
(4,存档),


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元:
订单= ['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(S tory,self).save()

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

category_list.html(相关模板):

  {%extendscms / base .html%
{%block content%}
< h1> Categories< / h1>
{%如果category_list%}
< ul id =category-list>
{category_list%中的类别%}
< li>< a href ={{category.get_absolute_url}}> {{category.label}}< / a> /立GT;
{%如果category.story_set%}
< ul>
{%for category.story_set.all%}
< li>< a href ={{story.get_absolute_url}}> {{story.title}}< /一个>< /锂>
{%endfor%}
< / ul>
{%endif%}
{%endfor%}
< / ul>
{%else%}
< p>
对不起,目前没有类别。
< / p>
{%endif%}
{%endblock%}


解决方案

我发现文档略有不清楚,但是 use_for_related_fields 管理器属性可能是你正在看的对于。当您尝试时,请注意,此功能使用 _default_manager ,这将始终指向在Model类中声明的第一个Manager,而不管其被赋予什么属性名称。您可以随时通过在相应的 ModelAdmin 类中覆盖 queryset 方法来自定义管理员网站中的哪些项目。



没有...

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

...和...

  {%for category.public_stories%} 

这至少避免了重复确定哪些故事可见的逻辑。


I'm in the progress of learning Django at the moment but I can't figure out how to solve this problem on my own. I'm reading the book Developers Library - Python Web Development With Django and in one chapter you build a simple CMS system with two models (Story and Category), some generic and custom views together with templates for the views.

The book only contains code for listing stories, story details and search. I wanted to expand on that and build a page with nested lists for categories and stories.

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

I managed to figure out how to add my own generic object_list view for the category listing. My problem is that the Story model have STATUS_CHOICES if the Story is public or not and a custom manager that'll only fetch the public Stories per default. I can't figure out how to tell my generic Category list view to also use a custom manager and only fetch the public Stories. Everything works except that small problem. I'm able to create a list for all categories with a sub list for all stories in that category on a single page, the only problem is that the list contains non public Stories.

I don't know if I'm on the right track here. My urls.py contains a generic view that fetches all Category objects and in my template I'm using the category.story_set.all to get all Story objects for that category, wich I then loop over.

I think it would be possible to add a if statement in the template and use the VIEWABLE_STATUS from my model file to check if it should be listed or not. The problem with that solution is that it's not very DRY compatible.

Is it possible to add some kind of manager for the Category model too that only will fetch in public Story objects when using the story_set on a category?

Or is this the wrong way to attack my problem?

Related code

urls.py (only category list view):

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 (related template):

{% 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 %}

解决方案

I find the documentation slightly unclear, but the use_for_related_fields Manager attribute may be what you're looking for. When you're trying it, note that this functionality uses _default_manager, which will always point at the first Manager declared in a Model class, regardless of what attribute name it's been given. You can always customise which items are editable in your admin site by overriding the queryset method in the appropriate ModelAdmin class instead.

Failing that...

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

...and...

{% for story in category.public_stories %}

This at least avoids duplicating the logic which determines which stories are viewable.

这篇关于Django经理为_set in model的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆