get_object_or_404()的第一个参数必须是Model,Manager或QuerySet,而不是“ unicode”

时间:2018-10-17 07:02:06

标签: python django

我是django的新手,我正在学习一些教程来学习它。在本教程中,我试图建立一个博客,但是我陷于以下错误中。

First argument to get_object_or_404() must be a Model, Manager, or QuerySet, not 'unicode'.
Request Method: GET
Request URL:    http://localhost:8000/blog/2018/10/16/todays_post/
Django Version: 1.11.16
Exception Type: ValueError
Exception Value:First argument to get_object_or_404() must be a Model, Manager, or QuerySet, not 'unicode'.
Exception Location: C:\Users\...\mysite\python-ve\env\lib\site-packages\django\shortcuts.py in get_object_or_404, line 90
Python Executable:  C:\Users\...\mysite\python-ve\env\Scripts\python.exe
Python Version: 2.7.15

以下是我的模型。py

from __future__ import unicode_literals
from django.core.urlresolvers import reverse
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager,self).get_queryset()\
        .filter(status='published')

class post(models.Model):
    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published','Published'),
    )

title = models.CharField(max_length=250) # field for the post title
slug = models.SlugField(max_length=250, unique_for_date='publish') 
author = models.ForeignKey(User, related_name ='blog_posts')
body = models.TextField()# text field. body of the post
publish = models.DateTimeField(default=timezone.now) 
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True) 
status = models.CharField(max_length = 10, 
choices=STATUS_CHOICES,default='draft') # to know the status of the post
objects = models.Manager()
published = PublishedManager()

class Meta: # sort results by the publish field in descending order
    ordering = ('-publish',)

def __str__(self):
    return self.title

def get_absolute_url(self):    
    return reverse('blog:post_detail', args[self.publish.year, 
    self.publish.strftime('%m'), self.publish.strftime('%d'), self.slug])

我的views.py,其中例外是:

from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404
from .models import post

def post_list(request):
    posts = post.published.all()
    return render(request, 'blog/post/list.html',{'posts':posts})

def post_detail(request, year, month,day,post):
    post = get_object_or_404(post, slug=post, status='published', 
    publish_year=year, publish_month=month, publish_day=day)
    return render(request, 'blog/post/detail.html', {'post':post})

我一直在寻找答案,有些我无法理解,所以我将其发布在这里。

3 个答案:

答案 0 :(得分:1)

视图中的变量和类的名称均为post,这意味着在您的视图中,我们看到:

def post_detail(request, year, month,day, post):
    post = get_object_or_404(post, slug=post, status='published', 
    publish_year=year, publish_month=month, publish_day=day)
    return render(request, 'blog/post/detail.html', {'post':post})
因此,

post本身是包含slug的局部变量(参数),并且它“隐藏”了引用模型的外部变量post。我建议您遵循 PEP-8 ,然后将您的post类重命名为Post(以大写字母开头,并且以驼峰字母开头)。如果您始终遵循PEP-8,则通常不会发生局部变量与类名之间的冲突。

一种快速(而不是优雅的)修复方法是使用其他名称导入模型:

from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404
from .models import post as post_model

def post_list(request):
    posts = post_model.published.all()
    return render(request, 'blog/post/list.html',{'posts':posts})

def post_detail(request, year, month,day,post):
    post = get_object_or_404(post_model, slug=post, status='published', 
    publish_year=year, publish_month=month, publish_day=day)
    return render(request, 'blog/post/detail.html', {'post':post})

但是我认为简单地使您的变量符合PEP-8绝对值得付出努力。

答案 1 :(得分:1)

将您的post类重命名为Post,并在post_detail视图中使用它。

post = get_object_or_404(Post, slug=post, status='published', publish_year=year, publish_month=month, publish_day=day)

在您的代码get_object_or_404中,函数尝试将视图中的post参数用作模型,但这是unicode。

对于类名,也要遵循UpperCaseCamelCase约定。

答案 2 :(得分:0)

重命名此代码块中的帖子

def post_detail(request, year, month,day, slug): post = get_object_or_404(post, slug=slug, status='published',
publish_year=year, publish_month=month, publish_day=day) return render(request, 'blog/post/detail.html', {'post':post})

然后要特别提示,因为模型是类,所以总是以大写字母开头来表示模型名称,这是一些好习惯。