我正在尝试创建一个表单以在作者详细信息页面上提交博客文章,以便该博客文章将自动使用当前作者作为其“ blog_author”外键。我知道这种方法不是“安全”的-它是一个项目站点,并且我正在尝试学习一种新的设计模式。 Django文档建议使用1个父视图和2个子视图分别处理get和post(https://docs.djangoproject.com/en/3.0/topics/class-based-views/mixins/)。
该页面使用get可以很好地呈现,但是该帖子给我一个错误,显示为“找不到页面(404)-找不到与查询匹配的博客帖子”。父视图(blog.views.AuthorDetail)引发了异常,但是没有回溯。
编辑:表格从一开始就应该是ModelForm
这是我的观点:
class BlogAuthorDetailView(generic.DetailView):
model = BlogAuthor
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = BlogSubmitForm()
return context
class BlogSubmit(SingleObjectMixin, FormView):
template_name = 'blogauthor_detail.html'
form_class = BlogSubmitForm
model = BlogPost
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
#Should I be overriding form_valid() to use the line above? Not sure if I'm doing my data
#handling in the right place
return super().post(request, *args, **kwargs)
def form_valid(self, form):
blogpost = form.save(commit=False)
blogpost.blog_author = self.object
blogpost.save()
return redirect('blog_author-detail', pk=self.object.id)
class AuthorDetail(View):
def get(self, request, *args, **kwargs):
view = BlogAuthorDetailView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = BlogSubmit.as_view()
return view(request, *args, **kwargs)
URL:
urlpatterns = [
path('', views.index, name='index'),
path('blogs/', views.BlogPostListView.as_view(), name='blogs'),
path('blog/<int:pk>', views.BlogPostDetailView.as_view(), name='blogpost-detail'),
path('bloggers/', views.BlogAuthorListView.as_view(), name='bloggers'),
path('blogger/<int:pk>', views.AuthorDetail.as_view(), name='blog_author-detail'),
path('blog/<int:pk>/create', views.BlogCommentCreate.as_view(), name='comment_create')
]
模板:
{% extends "base_generic.html" %}
{% block content %}
<h1>Title: {{ blogauthor.title }}</h1>
<p><strong>Author:</strong> <a href="">{{ blogauthor }}</a></p>
<p><strong>Biography:</strong> {{ blogauthor.biography }}</p>
<p><strong>User:</strong> {{ blogauthor.user }}</p>
<p><strong>Posts:</strong>
{% for blog in blogauthor.blogpost_set.all %}
<p> {{ blog.title }} </p>
{% endfor %} </p>
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
<div style="margin-left:20px;margin-top:20px">
<h4>Comments: Coming Soon!</h4>
{% endblock %}
型号:
class BlogPost(models.Model):
date_created = models.DateField(blank=False, default = date.today)
blog_author = models.ForeignKey('BlogAuthor', on_delete = models.SET_NULL, null=True)
title = models.TextField(max_length=70)
content = models.TextField(max_length=400, null=False)
class Meta:
ordering = ['date_created']
def get_absolute_url(self):
"""Returns the url to access a particular blog post instance."""
return reverse('blogpost-detail', args=[str(self.id)])
def __str__(self):
return self.title
forms.py:
class BlogSubmitForm(forms.Form):
title = forms.CharField()
content = forms.CharField(widget=forms.Textarea(attrs={'cols': 40, 'rows': 8}))
date_created = forms.DateField()
这时,我怀疑问题与form_valid覆盖中的redirect()调用有关。
我尝试过的事情包括:
edit:在我的本地服务器中显示的例外帖子之一转到了blog / blogger / 4,这是我想要的URL。不知道是什么问题。
答案 0 :(得分:1)
这使您对模板的使用方式感到困惑。无论如何,我认为这里最简单的解决方案是从BlogAuthor
获取request.user
数据,这是最合逻辑的,否则,任何人都可以向其他用户发布任何内容,只要他们可以预测其主键即可(是一个安全漏洞)。您可以尝试以下方法:
from django.contrib.auth.mixins import LoginRequiredMixin
class BlogSubmit(LoginRequiredMixin, CreateView):
template_name = 'blogauthor_detail.html'
form_class = BlogSubmitForm
model = BlogPost
def get_success_url(self):
return reverse('blog_author-detail', pk=self.object.id)
def form_valid(self, form):
form.blog_author = self.request.user.blogauthor # assuming BlogAuthor has OneToOne relation with User
return super(BlogSubmit, self).form_valid(form)
FormView的目的是从Forms收集数据,CreateView用来存储和创建新实例。无论如何,您需要像这样更改代码以使其正常工作:
class BlogSubmit(LoginRequiredMixin, SingleObjectMixin, FormView):
template_name = 'blogauthor_detail.html'
form_class = BlogSubmitForm
model = BlogAuthor
def get_success_url(self):
return reverse('blog_author-detail', pk=self.object.id)
def form_valid(self, form):
self.object = self.get_object()
form.blog_author = self.object
form.save()
return super(BlogSubmit, self).form_valid(form)
还更新表单:
class BlogSubmitForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'date_created', 'content']
仅供参考,要使SingleObjectMixin
有效,您需要将模型从BlogPost
更改为BlogAuthor