如何在Django ModelForm中不包含字段并使用其默认值填充?
解决方法
首先,你当前的代码存在两个关键问题:
- 模型中
author的default=get_user_model()配置错误,get_user_model()返回的是User模型类,而非当前登录的用户实例,这个默认值无法实现自动填充当前用户的效果。 pub_date的default=datetime.now()会导致所有新创建的Post使用服务器启动时的固定时间,而非实例创建的实时时间,正确写法应该去掉括号。
要实现不在表单显示author字段,同时自动用当前登录用户填充的需求,无需依赖模型默认值,正确做法是在视图层处理,步骤如下:
1. 修改表单,移除author字段
直接从fields和widgets中删除author相关配置,表单将不再渲染该字段:
# forms.py class PostForm(forms.ModelForm): class Meta: model = Post fields = ('title', 'body', 'logo') # 移除author字段 widgets = { 'title': forms.TextInput(attrs={'class': 'form-control bg-dark border border-secondary text-light'}), 'body': forms.Textarea(attrs={'class': 'form-control bg-dark border border-secondary text-light'}), 'logo': forms.ClearableFileInput(attrs={'class': 'form-control bg-dark border border-secondary text-light'}), }
2. 修正模型中的错误配置
# models.py from django.utils import timezone # 推荐使用Django内置的timezone模块 def get_file_path(instance, filename): file_extension = filename.split('.')[-1] return f'user_{instance.author}/{instance.pub_date.strftime("%Y/%B/%a-%M")}/logo.{file_extension}' class Post(models.Model): title = models.CharField(max_length=75) body = models.TextField() logo = models.ImageField(upload_to=get_file_path, blank=True) # 移除错误的default配置,后续在视图中设置author author = models.ForeignKey(User, on_delete=models.CASCADE) # 改用timezone.now且不带括号,确保每次创建实例时获取实时时间 pub_date = models.DateTimeField(default=timezone.now)
3. 在视图中重写form_valid方法,设置author
借助LoginRequiredMixin确保用户已登录,在表单保存前将当前用户赋值给author字段:
# views.py class PostCreateView(LoginRequiredMixin, CreateView): login_url = 'login' model = Post form_class = PostForm template_name = "posts/new_post.html" def form_valid(self, form): # 保存前为实例设置当前登录用户作为author form.instance.author = self.request.user # 调用父类方法完成后续保存逻辑 return super().form_valid(form)
这样处理后,表单页面不会显示author字段,提交时会自动将当前登录用户作为author存入数据库,完全符合你的需求,且无需使用隐藏字段。
内容的提问来源于stack exchange,提问作者X_ShaygaN_D
相关产品推荐
相关产品推荐

