Python 如何在CreateView中设置ForeignKey?
我有一个模型:Python 如何在CreateView中设置ForeignKey?,python,django,django-class-based-views,Python,Django,Django Class Based Views,我有一个模型: class Article(models.Model): text = models.CharField() author = models.ForeignKey(User) 如何编写基于类的视图来创建一个新的模型实例,并将author外键设置为request.user 更新: 解决方案移到下面的单独位置。您应该为该模型使用ModelForm设置CreateView。在表单定义中,您将ForeignKey设置为具有HiddenInput小部件,然后在视图上使用g
class Article(models.Model):
text = models.CharField()
author = models.ForeignKey(User)
如何编写基于类的视图来创建一个新的模型实例,并将author
外键设置为request.user
更新:
解决方案移到下面的单独位置。您应该为该模型使用
ModelForm
设置CreateView
。在表单定义中,您将ForeignKey
设置为具有HiddenInput
小部件,然后在视图上使用get\u form
方法设置用户的值:
forms.py:
from django import forms
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
widgets = {"user": forms.HiddenInput()}
views.py:
from django.views.generic import *
from myapp.forms import ArticleForm
from myapp.models import Article
class NewArticleView(CreateView):
model = Article
form_class = ArticleForm
def get_form(self, form_class):
initials = {
"user": self.request.user
}
form = form_class(initial=initials)
return form
Berislav在views.py中的代码不适合我。表单按预期呈现,用户值位于隐藏输入中,但表单未保存(我不知道为什么)。我尝试了一种稍微不同的方法,这种方法对我很有效: views.py
我通过重写
form\u valid
方法解决了这个问题。下面是详细的风格来澄清问题:
class CreateArticle(CreateView):
model = Article
def form_valid(self, form):
article = form.save(commit=False)
article.author = self.request.user
#article.save() # This is redundant, see comments.
return super(CreateArticle, self).form_valid(form)
然而,我们可以把它缩短(感谢dowjones123),这个案例是:
我只是偶然发现了这个问题,这条线索把我引向了正确的方向(谢谢!)。基于,我们完全可以避免调用表单的
save()
方法:
class CreateArticle(LoginRequiredMixin, CreateView):
model = Article
def form_valid(self, form):
form.instance.author = self.request.user
return super(CreateArticle, self).form_valid(form)
我尝试了这段代码,但它没有传递给用户查看,并且我无法保存新文章(因为需要
user
fiedl)。相反,我在CBV中使用了form_valid方法(请参阅相关更新。无论如何,感谢您有时间提供帮助!我不确定“不将用户传递到视图”是什么意思?它传递了用户ID并将其放入隐藏字段“user”。如果您需要视图中其他位置的用户(即模板),它已经在请求
变量中。我再次尝试了您的代码:在页面源中找不到任何隐藏的输入(csrf令牌除外)。为什么你认为这个字段会是用户的ID?为什么不是用户名?或者这只是CBV问题?见鬼,我的代码错了。现在修复了它。注意方法名称中的错误。绝对是最好的解决方案!应该是“get_initial”?让我们看看,如果我修改HTML代码并在表单中插入任何用户ID,你如何防止此类攻击用你的方法?@RichardCorden是对的,它是get_initial
(没有s
)+1。所有其他使用HIDDINPUT或设置首字母缩写的方法都可能存在安全风险。这并不理想,因为它会导致表单的save
方法被调用两次。在这种情况下,您的最佳选择是重新实现super
方法的其余部分,而不是委派。在其他情况下ords,将self.object
设置为新实例,然后重定向到self.get\u success\u url()
@orokusaki您完全正确。我查看了源代码,发现form\u valid
除了保存之外什么都不做(已验证)表单实例。因此,我们可以安全地删除super
或save
行。后者更好,因为我们不需要考虑成功的url
(否则我们需要显式设置)。更正了答案。@VladT。从技术上讲,它仍然不正确,因为表单的save方法仍在被调用两次(第一个是commit=False
),表单的保存方法中可能包含逻辑(甚至只是日志记录),您可能不想运行两次。如果您重新添加article.save()
,并将super(…)
行替换为返回重定向(self.get\u success\u url())
,这将是最正确的解决方案。更有效的方法(观点可能不同)是将form\u valid
的前两行替换为form.instance.author=self.request.user
class CreateArticle(CreateView):
model = Article
def form_valid(self, form):
form.instance.author = self.request.user
return super(CreateArticle, self).form_valid(form)
class CreateArticle(LoginRequiredMixin, CreateView):
model = Article
def form_valid(self, form):
form.instance.author = self.request.user
return super(CreateArticle, self).form_valid(form)