Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在CreateView中设置ForeignKey?_Python_Django_Django Class Based Views - Fatal编程技术网

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)