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')
错误原因及解决方案
核心错误点
- 表单继承错误:用了
forms.Form而非forms.ModelForm,CreateView/UpdateView需要绑定模型的表单才能自动处理QuerySet和实例,普通Form无模型关联,导致视图找不到对应QuerySet。 - 视图属性错误:通用视图识别
form_class而非form_name,且Create和Update的表单被搞反。 - 表单Meta类写法错误:ModelForm的Meta需指定
model和fields,自定义widget要放在widgets字典里,原写法完全不符合规范。 - 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
相关产品推荐
相关产品推荐

