Skip to main content
 首页 » 编程设计

python之在 CreateView 中设置值的更好方法

2025年05月04日16lovecherry

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 文档中找到对该逻辑的引用:

https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-editing/#models-and-request-user


理想情况下,对于 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)