Django modelManager-在视图/列表视图中看不到实例/对象-无错误

时间:2019-05-06 11:04:35

标签: django django-models django-views

我是django的新手。我正在尝试仅使用models.Manager个实例与published=True显示。在终端中没有错误。我做错了什么?我觉得这与我的观点有关。

任何帮助将不胜感激。

models.py

from django.db import models

# Create your models here.
class BlogPostManager(models.Manager):

    use_for_related_fields = True
    def freetosee(self, **kwargs):
        return self.filter(published=True, **kwargs)

class Post(models.Model):
    NOT_RATED = 0
    RATED_G = 1
    RATED_PG = 2
    RATED_R = 3

    RATINGS =(
        (NOT_RATED, 'NR-Not Rated'),
        (RATED_G, 'G - General Audience'),
        (RATED_PG, 'Parental'),
        (RATED_R, 'Restriced'),
    )

    title = models.CharField(max_length=140)
    body = models.TextField()
    published = models.BooleanField(default=False)
    rating = models.IntegerField(
        choices=RATINGS,
        default=NOT_RATED,
    )
    objects = BlogPostManager()


    def __str__(self):
        return self.title

views.py

from django.shortcuts import render

# Create your views here.
from django.views.generic import DetailView, ListView
from .models import Post


class PostListView(ListView):
    model = Post
    context_object_name = 'posts'
    template_name = 'postlist.html'

模板

{% extends "base.html" %}

{% block content %}

    {% for post in posts.objects.freetosee %}
        {{ post.title }} - {{ post.body }}
    {% endfor %}

{% endblock %}

urls.py

from django.urls import path, include
from django.views.generic import TemplateView
from .views import PostListView

app_name = 'blog'

urlpatterns = [
    path('', TemplateView.as_view(template_name='home.html'), name='home'),
    path('list/', PostListView.as_view(), name='post-list'),
]

我希望看到ListViewpublished=True的所有模型实例

2 个答案:

答案 0 :(得分:1)

这不是它的工作方式。 posts是一个查询集,没有objects属性。您需要在视图中调用它:

class PostListView(ListView):
    queryset = Post.objects.freetosee()
    context_object_name = 'posts'
    template_name = 'postlist.html'

然后在模板中执行{% for post in posts %}

答案 1 :(得分:1)

由于您使用的是2.1 根据{{​​3}} use_for_related_fields = True删除 您必须在模型base_manager_name中使用Meta。像这样:

class Post(models.Model):
    # your fields here
    objects = BlogPostManager()

    class Meta:
        base_manager_name = 'objects'

如上面注释中所建议的,当您设置了context_object_name时,您不必做posts.objects.freetouse

将模板更改为:

{% extends "base.html" %}

{% block content %}
    {% for post in posts %}
        {{ post.title }} - {{ post.body }}
    {% endfor %}    
{% endblock %}
来自django 2.0 deprecation docs

ListView有一个get_queryset()方法,我们可以重写。以前,它只是返回queryset属性的值,但是现在我们可以添加更多逻辑。

这意味着您可以

class PostListView(ListView):
    queryset = Post.objects.freetosee()
    context_object_name = 'posts'
    template_name = 'postlist.html'

,您也可以这样做:

class PostListView(ListView):
    context_object_name = 'posts'
    template_name = 'postlist.html'

    def get_queryset(self):
        # this method can be used to apply as many filters as you want
        # Just a quick example, 
        # filter_id = self.request.GET.get('filter_by')
        # if filter_id:
        #     return Post.objects.filter(id=filter_id)
        return Post.objects.freetosee()

注意::请理解Views在那里可以处理所有数据,并将其传递给templates。您进行managers来将自定义查询方法放在一个位置。因此,它是一种事物的场所,除非非常必要,否则您的模板不应发出任何查询请求。 templates仅用于显示。如果要在filters中使用templates,请使用模板标记。这样可以使您的代码干净且可读。