models.py:
class BlogPost(models.Model):
title = models.CharField(max_length=200)
post_body = models.TextField()
user = models.ForeignKey(User)
pub_date = models.DateTimeField('published')
def get_absolute_url(self):
return u'/entries/%d' % self.id
forms.py:
class NewPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ('title', 'post_body')
所以,我试图为用户创建一个 View ,以便将新帖子发布到博客中。 BlogPost 模型有 4 个字段 - title、post_body、user 和 pub_date。用户应该能够填写 title 和 post_body,而其他两个应该自动填写。我尝试的第一件事是:
class NewPostView(generic.edit.CreateView):
model = BlogPost
form_class = NewPostForm
def get_initial(self):
return {'pub_date': timezone.now(),
'user': self.request.user}
但它唯一做的就是为 html 表单提供默认值。经过进一步研究,这是最终有效的代码:
class NewPostView(generic.edit.CreateView):
model = BlogPost
form_class = NewPostForm
def form_valid(self, form):
obj = form.save(commit=False)
obj.user = self.request.user
obj.pub_date = timezone.now()
obj.save()
return HttpResponseRedirect(obj.get_absolute_url())
所以,虽然重写 form_valid 方法有效,但我不觉得它应该如何完成?有没有更好的地方来放置这个 Action ?这样做的常规方法是什么?
请您参考如下方法:
您可以覆盖 form_valid,然后在返回语句中调用 super().form_valid(form)。您不必担心保存表单、保存对象或返回 HttpResponseRedirtect。所有这些都将由 super 处理。您需要做的就是设置要在后台控制的 form.instance 的值。
views.py
class NewPostView(generic.edit.CreateView):
model = BlogPost
form_class = NewPostForm
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.pub_date = timezone.now()
return super().form_valid(form)
这将是一种在幕后添加值的简洁方法,不需要您执行比添加值更多的逻辑操作。您可以在 django 文档中找到对该逻辑的引用:
理想情况下,对于 pub_date,您希望将字段设置为使用 auto_now_add 自动记录创建时间。
模型.py
class BlogPost(models.Model):
title = models.CharField(max_length=200)
post_body = models.TextField()
user = models.ForeignKey(User)
pub_date = models.DateTimeField('published', auto_add_now=True)
def get_absolute_url(self):
return u'/entries/%d' % self.id
您可以在下面的链接中找到有关 DateTimeField 的文档及其对 auto_add_now 参数的引用。它还有一个 auto_add,每次修改条目时都会更新,以防您需要一个 last_edited_date 字段。
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.DateTimeField
此外,您的用户有可能在未登录的情况下访问表单。您需要处理未设置 self.request.user 的情况,或者您可以使用LoginRequiredMixin 只允许登录用户访问此表单。我使用 mixin 的时间更轻松了。
经过上述所有更改后生成的 view.py 如下所示。
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
from .forms import NewPostForm
from .models import BlogPost
class NewPostView(LoginRequiredMixin, CreateView):
model = BlogPost
form_class = NewPostForm
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
