You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django博客表单加占位符后出现QuerySet缺失错误的解决求助

Django博客表单占位符添加及QuerySet错误解决

问题描述

我用Django开发博客,想给文章创建和编辑表单的输入框加占位符。之前只用models.py,新增forms.py实现这个需求后,网站出现了QuerySet相关错误(创建和编辑文章表单都触发同样的错误)。查资料说要在views.py里给对应表单加get_queryset方法,但不知道这个方法具体怎么写、放在哪,附上相关代码求助。

原代码

views.py

class BlogHome(ListView):
    model = BlogPost
    context_object_name = "posts"

    def get_queryset(self):
        queryset = super().get_queryset()
        if self.request.user.is_authenticated:
            return queryset
        else:
            return queryset.filter(published=True)


@method_decorator(login_required, name='dispatch')
class BlogPostCreate(CreateView):
    form_name = UpdatePostForm

class BlogPostEdit(UpdateView):
    form_name = CreatePostForm

urls.py

urlpatterns = [
    path('create/', BlogPostCreate.as_view(), name="create"),
    path('edit/<str:slug>/', BlogPostEdit.as_view(), name="edit"),
]

forms.py

from django import forms
from posts.models import BlogPost

class UpdatePostForm(forms.Form):
    model = BlogPost
    template_name = 'posts/blogpost_edit.html'
    fields = [
        'title',
        'slug',
        'content', 
        'published', 
        'author', 
        'created_on'
    ]

    class Meta:
        title = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        slug = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        content = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        created_on = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the date of creation'}),
        ),

class CreatePostForm(forms.Form):
    model = BlogPost
    template_name = 'posts/blogpost_create.html'
    fields = [
        'title',
        'slug',
        'content', 
        'published', 
        'author', 
        'created_on'
    ]

    class Meta:
        title = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        slug = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        content = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the title of the article'}),
        ),
        created_on = forms.CharField(
            widget = forms.TextInput(attrs={'placeholder' : 'Enter the date of creation'}),
        ),

models.py

from django.contrib.auth import get_user_model
from django.template.defaultfilters import slugify
from django.db import models
from django.urls import reverse

User = get_user_model()


class BlogPost(models.Model):
    title = models.CharField(max_length=255, unique=True, verbose_name="Titre")
    slug = models.SlugField(max_length=255, unique=True, blank=True)
    author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
    last_updated = models.DateTimeField(auto_now=True)
    created_on = models.DateField(blank=True, null=True)
    published = models.BooleanField(default=False, verbose_name="Publié")
    content = models.TextField(blank=True, verbose_name="Contenu")
    thumbnail = models.ImageField(blank=True, upload_to='blog')

    class Meta:
        ordering = ['-created_on']
        verbose_name = "Article"

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)

        super().save(*args, **kwargs)

    @property
    def author_or_default(self):
        return self.author.username if self.author else "L'auteur inconnu"

    def get_absolute_url(self):
        return reverse('posts:home')

错误原因及解决方案

核心错误点

  1. 表单继承错误:用了forms.Form而非forms.ModelForm,CreateView/UpdateView需要绑定模型的表单才能自动处理QuerySet和实例,普通Form无模型关联,导致视图找不到对应QuerySet。
  2. 视图属性错误:通用视图识别form_class而非form_name,且Create和Update的表单被搞反。
  3. 表单Meta类写法错误:ModelForm的Meta需指定model和fields,自定义widget要放在widgets字典里,原写法完全不符合规范。
  4. UpdateView缺少模型/QuerySet定义:UpdateView需明确从哪个模型获取编辑对象。

修正后的代码

forms.py

from django import forms
from posts.models import BlogPost

class CreatePostForm(forms.ModelForm):
    class Meta:
        model = BlogPost
        fields = ['title', 'slug', 'content', 'published', 'author', 'created_on']
        widgets = {
            'title': forms.TextInput(attrs={'placeholder': '输入文章标题'}),
            'slug': forms.TextInput(attrs={'placeholder': '输入文章slug(留空将自动生成)'}),
            'content': forms.Textarea(attrs={'placeholder': '输入文章内容'}),
            'created_on': forms.DateInput(attrs={'placeholder': '输入创建日期', 'type': 'date'}),
        }

# 编辑表单和创建表单字段一致可复用,这里分开写示例
class UpdatePostForm(forms.ModelForm):
    class Meta:
        model = BlogPost
        fields = ['title', 'slug', 'content', 'published', 'author', 'created_on']
        widgets = {
            'title': forms.TextInput(attrs={'placeholder': '修改文章标题'}),
            'slug': forms.TextInput(attrs={'placeholder': '修改文章slug'}),
            'content': forms.Textarea(attrs={'placeholder': '修改文章内容'}),
            'created_on': forms.DateInput(attrs={'placeholder': '修改创建日期', 'type': 'date'}),
        }

views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, CreateView, UpdateView
from posts.models import BlogPost
from posts.forms import CreatePostForm, UpdatePostForm

class BlogHome(ListView):
    model = BlogPost
    context_object_name = "posts"

    def get_queryset(self):
        queryset = super().get_queryset()
        if self.request.user.is_authenticated:
            return queryset
        else:
            return queryset.filter(published=True)

class BlogPostCreate(LoginRequiredMixin, CreateView):
    model = BlogPost
    form_class = CreatePostForm
    template_name = 'posts/blogpost_create.html'
    success_url = '/'  # 可自定义跳转逻辑

class BlogPostEdit(LoginRequiredMixin, UpdateView):
    model = BlogPost
    form_class = UpdatePostForm
    template_name = 'posts/blogpost_edit.html'
    slug_field = 'slug'
    slug_url_kwarg = 'slug'

    # 可选:限制用户仅能编辑自己的文章
    def get_queryset(self):
        queryset = super().get_queryset()
        # 超级管理员可编辑所有,普通用户仅能编辑自己发布的文章
        if self.request.user.is_superuser:
            return queryset
        return queryset.filter(author=self.request.user)

关键说明

  • ModelForm的作用:绑定模型后,表单自动从模型字段生成表单字段,同时支持视图自动处理实例的创建与更新,这是解决QuerySet错误的核心。
  • get_queryset的用法:在UpdateView中重写该方法主要用于权限控制,比如限制用户仅能编辑自己的文章。若无权限需求,仅指定model = BlogPost即可,视图会自动获取默认QuerySet。
  • Widget优化:content是TextField,用Textarea更合适;created_on是DateField,指定type='date'可调用浏览器日期选择器,提升体验。

内容的提问来源于stack exchange,提问作者Khomy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:50:54