通过传递基于实例类的视图Djang,允许在模型具有必需字段的情况下提交modelform

2024-04-19 20:49:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一种编辑表单样式,我曾经使用过这样一种方式:通过告诉表单它正在编辑一个实例,而不是生成一个新的pk,从而允许用户提交表单:

edit_form = PrivateProfileForm(data=request.POST, instance=profile)

有问题的应用程序有一个具有必需的、唯一字段的模型,该字段应为(url):

^{pr2}$

在基于类的视图中,传递instance=article表单的几次尝试都失败了,尽管是静默的,最近的一次失败是尝试form.instance = article_in_question

查看帖子:

 class ArticleUpdateView(UpdateView):
    model           = Article
    form_class      = EditArticleForm
    template_name   = 'index/edit_article.html'

    def get_context_data(self, **kwargs):
        context = super(ArticleUpdateView, self).get_context_data(**kwargs)
        context['tags'] = Tag.objects.all() 
        return context

    def add_tags(self, article, tags_to_add):
        for tag in tags_to_add:
            article.tags.add(tag)

    def form_invalid(self, **kwargs):
        return self.render_to_response(self.get_context_data(**kwargs))

    def post(self, request,  *args, **kwargs):
        self.object = None
        article_in_question = Article.objects.get(pk=self.kwargs['pk'])
        print article_in_question
        form_class = self.get_form_class()
        form_name = 'form'
        form = self.get_form(form_class)
        if form.is_valid():
            tags_chosen = request.POST.getlist('selected_tags')
            form.instance = article_in_question
            article = form.save(commit=False)
            article.save()
            self.add_tags(article, tags_chosen)
            return self.form_valid(form)
        else:
            return self.form_invalid(**{form_name: form})

Tag和Article是独立的模型,所以我还没有找到一种方法将它们轻松地集成到一个表单中。在视图中添加标记很好,并且可以创建文章,所以我只想允许提交这个预先填充的表单,而不尝试创建新的模型(由于独特的需求而失败)。在

我当前编辑表单和原始表单进行比较:

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ('url', 'title', 'user')

    url     = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'required'}),
                  max_length=256, label='URL', required=True)    
    title   = forms.CharField(widget=forms.TextInput(attrs={"placeholder": "I'll grab the page's title"}),
                  max_length=256, label='Title', required=False)
    user    = forms.CharField(widget=forms.HiddenInput()) 

    def clean(self):
        try:
            title = self.cleaned_data['title']
            url   = self.cleaned_data['url']
            title = process_title(url)
            self.cleaned_data['title'] = title
        except:
            pass
        username = self.cleaned_data['user'] 
        user = User.objects.get(username=username)
        self.cleaned_data['user'] = user
        super(ArticleForm, self).clean()
        return self.cleaned_data


class EditArticleForm(forms.ModelForm):
    url     = forms.CharField(required=False)
    title   = forms.CharField(required=False)
    class Meta:
        model = Article
        fields = ('url', 'title')

我将表单称为与创建对象时相同的形式,并且在视图中,article_in_question将作为真实的文章出现。如果您感兴趣,模板如下所示(与创建对象的表单相同):

<form id="article_form" method="post" action="" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form|bootstrap }}
    {% for tag in tags %}
        <div style="display:inline-block;" >
            <input type="checkbox" name="selected_tags" id="option{{tag.id}}" value={{tag.name}} />
            <label for="option{{tag.id}}">{{tag.name}}</label>
        </div>
    {% endfor %}
<br/>
<input type="submit" name="submit" value="Edit article"/>

在贝壳里看到:

In [5]: v = ArticleUpdateView()

In [8]: v.form_class
Out[8]: index.forms.EditArticleForm

In [14]: a = Article.objects.create(url='fake.com', title="fake")

In [15]: a
Out[15]: <Article: fake>

In [19]: form =v.form_class(instance=a)

In [20]: form
Out[20]: <EditArticleForm bound=False, valid=Unknown, fields=(url;title)>

我很惊讶:

    form_class = self.get_form_class()
    form_class.instance = article_in_question
    print form_class.instance
    form_name = 'form'
    form = self.get_form(form_class)

没用。打印form_class.instance表明适当的文章附加到了该表单类。在

如何告诉窗体它正在这些基于类的视图中的实例上工作?在


Tags: instancenameinselfformurl表单data
1条回答
网友
1楼 · 发布于 2024-04-19 20:49:31

别担心。如果其他学习类视图的人Django想学习这个,请注意form = self.get_form(form_class)正在内部执行一个覆盖instance到{}的操作。解决办法是:

    form_class = self.get_form_class()
    form_name = 'form'
    form = self.get_form(form_class)
    form.instance = article_in_question

了解这些复杂的类视图的方法是进入ipython并获取一个类似的

^{pr2}$

然后直接玩它的物品:

In [24]: v.
v.add_tags                 v.get_template_names
v.as_view                  v.http_method_names
v.content_type             v.http_method_not_allowed
v.context_object_name      v.initial
v.dispatch                 v.model
...etc...

事实证明,这比读几个小时的文档要有效得多;虽然非常全面,但在许多情况下,它们似乎缺乏实际的例子

相关问题 更多 >