我有一个模型:
class Article(models.Model):
text = models.CharField()
author = models.ForeignKey(User)
我该如何编写基于类的视图来创建一个新的模型实例,并将author
外键设置为request.user
?
更新:
解决方案已移至下面的单独的答案。
我有一个模型:
class Article(models.Model):
text = models.CharField()
author = models.ForeignKey(User)
我该如何编写基于类的视图来创建一个新的模型实例,并将author
外键设置为request.user
?
更新:
解决方案已移至下面的单独的答案。
我通过重写 form_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的建议,我们可以使它更简短,这种情况在文档中有提到:mentioned in docs
class CreateArticle(CreateView):
model = Article
def form_valid(self, form):
form.instance.author = self.request.user
return super(CreateArticle, self).form_valid(form)
save
方法被调用两次。这是那种情况之一,你最好重新实现剩余的 super
方法,而不是委派。换句话说,将 self.object
设置为新的实例,然后重定向到 self.get_success_url()
。 - orokusakiform_valid
除了保存(已验证)表单实例之外什么也没有做。因此,我们可以安全地删除super
或save
行。后者更好,因为我们不需要考虑success_url
(否则我们需要明确设置它)。修正了答案。 - Vlad T.commit=False
),而表单的保存方法可能具有您不希望运行两次的逻辑(甚至只是日志记录)。如果您添加回article.save()
并将super(...)
行替换为return redirect(self.get_success_url())
,那将是最正确的解决方案。 - orokusakiform_valid
的前两行替换为form.instance.author = self.request.user
。 - dowjones123我刚刚遇到了这个问题,这个线程引导了我走向正确的方向(谢谢!)。根据这个Django文档页面,我们可以完全避免调用表单的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)
你应该使用 CreateView
和一个 ModelForm
来设置那个模型。在表单定义中,你可以设置 ForeignKey
为 HiddenInput
形式,然后在视图中使用 get_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
request
变量中了。 - Berislav LopacBerislav在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_initial(self):
return {
"user": self.request.user
}
get_initial
(没有 s
)。 - TKrugg有些答案主要涉及到User
模型外键。然而,让我们假设一个简单的场景,其中有一个包含Article
模型外键的Comment
模型,并且您需要为Comment
创建一个CreateView
,其中每个评论都将具有Article
模型的外键。在这种情况下,Article
id可能会出现在URL
中,例如:/article/<article-id>/comment/create/
。以下是如何处理这种情况的方法。
class CommentCreateView(CreateView):
model = Comment
# template_name, etc
def dispatch(self, request, *args, **kwargs):
self.article = get_object_or_404(Article, pk=self.kwargs['article_id'])
return super(CommentCreateView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
form.instance.article= self.article # if the article is not a required field, otherwise you can use the commit=False way
return super(CommentCreateView, self).form_valid(form)