ArticlePostUpdateView未向更新模板传数据,slug为空求助
问题描述
论坛帖子更新功能正常,但文章更新功能失效:article_update_form 模板无法从视图接收数据,导致slug为空;手动通过get_context_data传递post到模板后,表单又无法渲染forms.py中的组件。
模型代码
class ArticlePost(models.Model): title = models.CharField(max_length=400) slug = models.CharField(max_length=400, unique=True, blank=True) article_users = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="article_users") content = models.TextField() categories = models.ManyToManyField(ArticleCategory) date = models.DateTimeField(auto_now_add=True) approved = models.BooleanField(default=False) hit_count_generic = GenericRelation(HitCount, object_id_field="object_pk", related_query_name="hit_count_generic_relation") article_tags = TaggableManager(related_name="article_tags") article_image = models.ImageField(null=True, blank=True, upload_to="article_images/") def __str__(self) -> str: return self.title @property def length(self) -> int: return len(self.content) @property def get_category(self): return [v for v in self.categories.all()] def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super(ArticlePost, self).save(*args, **kwargs) def get_absolute_url(self): return reverse("article_details", kwargs={ "slug": self.slug })
UpdateView代码
class ArticlePostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = ArticlePost template_name = 'articles/article_form_update.html' form_class = ArticlePostForm def form_valid(self, form): form.instance.author = self.request.user messages.success(self.request, 'The article has been updated') return super().form_valid(form) def test_func(self): post = self.get_object() if self.request.user.id == post.article_users.user.id: return True return False
路由代码
urlpatterns = [ path("posts/<slug>/", articles, name="articles"), path('<int:page_id>', pages.views.articles, name='page'), path("detail/<slug>/", detail, name="article_details"), path("new_article", new_article, name="new_article"), path("new_article/create_post", login_required(ArticlePostCreateView.as_view()), name="create_article"), path("post/<slug:slug>/update/", ArticlePostUpdateView.as_view(), name="update_post_article"), path('categories_list', categories_list, name="categories_list"), path("search_article_post", search_article_post, name="search_article_post"), path("category/<slug>/", category_articles, name="category_articles"), path("sort_by/<str:typesort>", articles_sort, name="articles_sort"), ]
表单代码
class ArticlePostForm(forms.ModelForm): class Meta: model = ArticlePost fields = ("title", "categories", "content", "article_tags", 'article_image') exclude = ["article_users"] widget = { 'title': forms.TextInput(attrs={'class': 'form-control'}), 'content': forms.TextInput(attrs={'class': 'form-control'}), 'categories': forms.Select(attrs={'class': 'form-control'}), 'article_tags': forms.Select(attrs={'class': 'form-control'}), 'article_image': forms.Select(attrs={'class': 'form-control'}), } def __setitem__(self, i, elem): self.list[i] = elem
表单模板代码
<div class="form-group"> <form method="POST" action="{% url 'update_post_article' slug=post.slug %}"> {% csrf_token %} <div class="centered_create_post"> {% render_field form.title placeholder="Enter title" class+="form-control each_post_create" %} {% render_field form.content placeholder="Enter content" class+="form-control each_post_create pst_create_categories " %} {% render_field form.categories class+="form-control each_post_create pst_create_categories " %} {% render_field form.article_image class+="form-control each_post_create" %} <div class="pull-left"><button type="submit" class="btn_create_post">Update Post</button></div> </div> <div class="clearfix"></div> </div> <div class="clearfix"></div> </div> </form>
问题修复方案
1. 修正UpdateView字段赋值错误
模型中关联作者的字段是article_users(关联Author模型),不是author,需修改form_valid方法:
def form_valid(self, form): # 假设当前用户对应唯一的Author实例,可根据实际关联逻辑调整 form.instance.article_users = Author.objects.get(user=self.request.user) messages.success(self.request, '文章已更新') return super().form_valid(form)
2. 修复模板上下文与表单提交路径
- UpdateView默认将当前对象放入上下文,变量名为
object或模型小写形式articlepost;如果需要post变量,在视图中添加:
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['post'] = self.get_object() return context
- 表单可省略
action属性,Django会自动处理提交路径;若保留则使用{{ post.slug }}(需确保post在上下文):
<form method="POST" action="{% url 'update_post_article' slug=post.slug %}">
3. 修复表单类错误
- 修正widget拼写:Meta类中应为
widgets(复数),否则样式不生效; - 删除多余方法:移除
__setitem__方法,该方法会破坏表单内部结构导致组件无法渲染; - 匹配字段对应widget类型:
content是TextField,改用forms.Textarea;categories是ManyToManyField,改用SelectMultiple或CheckboxSelectMultiple;article_tags是TaggableManager,使用TagWidget(需导入from taggit.forms import TagWidget);article_image是ImageField,改用ClearableFileInput;
修改后的表单类:
from taggit.forms import TagWidget class ArticlePostForm(forms.ModelForm): class Meta: model = ArticlePost fields = ("title", "categories", "content", "article_tags", 'article_image') exclude = ["article_users"] widgets = { 'title': forms.TextInput(attrs={'class': 'form-control'}), 'content': forms.Textarea(attrs={'class': 'form-control'}), 'categories': forms.SelectMultiple(attrs={'class': 'form-control'}), 'article_tags': TagWidget(attrs={'class': 'form-control'}), 'article_image': forms.ClearableFileInput(attrs={'class': 'form-control'}), }
4. 修复模板渲染依赖
若使用{% render_field %},需在模板顶部加载crispy标签:
{% load crispy_forms_tags %}
内容的提问来源于stack exchange,提问作者Blade Runner
相关产品推荐
相关产品推荐

