gerente de Django para _set no modelo

votos
4

Estou no progresso da aprendizagem Django no momento, mas eu não consigo descobrir como resolver este problema sozinha. Estou lendo o livro Developers Biblioteca - Python desenvolvimento web com Django e em um capítulo que você construir um sistema CMS simples, com dois modelos (História e Categoria), alguns pontos de vista genéricos e personalizados em conjunto com modelos para as vistas.

O livro contém apenas código para histórias da lista, detalhes da história e pesquisa. Eu queria expandir sobre isso e construir uma página com listas aninhadas para categorias e histórias.

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

Eu consegui descobrir como adicionar minha própria visão object_list genérico para a listagem categoria. Meu problema é que o modelo de história tem STATUS_CHOICES Se a história é público ou não, e um gerenciador customizado que só vai buscar os Stories públicos por padrão. Eu não consigo descobrir como dizer a minha opinião Categoria lista genérica para também usar um gerenciador customizado e só buscar os Stories públicas. Tudo funciona, exceto que pequeno problema. Eu sou capaz de criar uma lista de todas as categorias, com uma lista de sub para todas as histórias dessa categoria em uma única página, o único problema é que a lista contém histórias não públicos.

Eu não sei se estou no caminho certo aqui. Meu urls.py contém uma visão genérica que agrupa todos os objetos categoria e em meu modelo Eu estou usando o category.story_set.all para obter todos os objetos da história para essa categoria, wich Eu, então, varrer.

Eu acho que seria possível adicionar uma declaração se no modelo e usar o VIEWABLE_STATUS do meu arquivo de modelo para verificar se ele deve ser listado ou não. O problema com essa solução é que ela não é muito seco compatível.

É possível adicionar algum tipo de gestor para o modelo Categoria também que só vai buscar em objetos da história públicos ao utilizar o story_set em uma categoria?

Ou esta é a maneira errada de atacar o meu problema?

código relacionado

urls.py (somente lista de categorias de vista):

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 (modelo relacionado):

{% 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 %}
Publicado 19/02/2009 em 00:40
fonte usuário
Em outras línguas...                            


4 respostas

votos
11

I encontrar a documentação ligeiramente obscura, mas o atributo pode ser o que você está procurando. Quando você está tentando isso, note que esta funcionalidade utiliza , que será sempre apontar para o primeiro Gerente declarou em uma classe Model, independentemente do que atributo de nome que tem sido dado. Você sempre pode personalizar quais itens são editáveis no seu site de administração, substituindo o método no apropriada classe em vez.use_for_related_fields Manager_default_managerquerysetModelAdmin

Falhando naquilo...

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

...e...

{% for story in category.public_stories %}

Esta, pelo menos evita duplicar a lógica que determina quais histórias são visíveis.

Respondeu 19/02/2009 em 16:08
fonte usuário

votos
4

Se você quer uma solução específica modelo que você pode criar um filtro personalizado. Desta forma, você pode evitar tocar sua classe de modelo

Este será o seu filtro:

from django import template

register = template.Library()

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

E você pode usá-lo em seu modelo

{% category.story_set|viewable %}
Respondeu 10/10/2009 em 19:29
fonte usuário

votos
2

Basta alterar as posições dos seus declarações gerente.

A partir de

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

Para

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

De acordo com a documentação :

O gerenciador padrão em uma classe ou é o primeiro gerente declarou na classe, se existe, ou o gerente padrão da primeira classe base abstrata na hierarquia pai, se o que existe. Se nenhum gerenciador padrão é explicitamente declarado, gerenciador padrão normais do Django é usado.

Respondeu 13/03/2010 em 02:04
fonte usuário

votos
2

Para elaborar resposta de @ insin, você deve adicionar use_for_related_fields = Trueà ViewableManagerclasse. Dessa forma, Category.story_setirá retornar uma instância do gerenciador de costume, que tem o get_query_setmétodo que você precisa. Sua tag será semelhante

{% category.story_set.get_query_set %}

Editar : @ resposta de insin é muito melhor, eu uso isso.

Respondeu 19/02/2009 em 16:21
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more