在 django View 类中访问表单“字段”

Posted

技术标签:

【中文标题】在 django View 类中访问表单“字段”【英文标题】:Access form 'fields' in django View class 【发布时间】:2021-09-05 05:15:19 【问题描述】:

我正在尝试访问基于类的视图中的“字段”属性

这是我的 forms.py 的示例:

from django import forms
from .models import ErrorEvent


class ErrorEventForm(forms.ModelForm):

    class Meta:
        model = HumanErrorEvent
        # fields =
        exclude = ['event_id', 'user_modified', 'date_modified']
        widgets = 
            'owner': forms.TextInput(),
        

那么这是我的看法:

class ErrorCreateView(CreateView):
    template_name = "forms/form.html"
    form_class = ErrorEventForm
    model = ErrorEvent

    def get_context_data(self, **kwargs):
        if not self.request.user.groups.filter(name='leaders').exists():
            self.form_class.fields['owner'].widget = forms.HiddenInput()
        context = super(ErrorCreateView, self).get_context_data(**kwargs)
        return context

我得到的错误是:

AttributeError: type object 'ErrorEventForm' has no attribute 'fields'

由于这一行:

self.form_class.fields['owner'].widget = forms.HiddenInput()

是否无法访问视图中的“字段”属性?如果没有,有没有办法根据用户所在的组隐藏“所有者”表单字段?

提前感谢您的所有帮助!

【问题讨论】:

为什么在提交表单时隐藏用户,而不是简单地使用request.user 这是通常的做法,但我希望能够让某些人有权更改所有者或以其他人的名义创建所有者。 然后您可以在表单中添加ModelChoiceField 这如何解决我的问题? @mike_gundy123 表单的fields 属性仅在实例化时添加到表单中。表单类本身没有它。 get_context_data 也不是最好的覆盖方法。 【参考方案1】:

表单的fields属性只有在表单被实例化时才添加,表单类本身没有。此外,get_context_data 不是覆盖做此类事情的最佳方法,更好的方法可能是 get_form,因此您可以编写如下内容:

def get_form(self, form_class=None):
    form = super().get_form(form_class=form_class)
    form.fields['owner'].widget = forms.HiddenInput()
    return form

但我们仍然可以做得比这更好!这样的逻辑不应该属于表单类本身吗?因此,最好将用户简单地传递给表单类。您可以通过覆盖 get_form_kwargs 和表单 __init__ 方法来做到这一点:

# Form
class ErrorEventForm(forms.ModelForm):

    class Meta:
        model = HumanErrorEvent
        # fields =
        exclude = ['event_id', 'user_modified', 'date_modified']
        widgets = 
            'owner': forms.TextInput(),
        
    
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        if user and not user.groups.filter(name='leaders').exists():
            del self.fields['owner']  # Remove the field itself from the form
            self.instance.owner = user  # Set the user as the owner


# View
class ErrorCreateView(CreateView):
    template_name = "forms/form.html"
    form_class = ErrorEventForm
    model = ErrorEvent
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

【讨论】:

感谢您的帮助!这些线有什么意义? super().__init__(*args, **kwargs) kwargs = super().get_form_kwargs() 另外我将如何在 html 端处理这个问题? form.owner|as_crispy_field 但是当我删除它时我得到一个错误,因为它不存在 @mike_gundy123 super().<method_call> 只是调用了 super 方法,我相信您已经在使用类似super(ErrorCreateView, self).get_context_data(**kwargs) 的方法(您可以跳过 python3 中的两个参数)?至于那个错误,我原以为您是直接渲染表单,要解决它,您可以将其括在 if 中:% if form.owner %<div class="col-md-3"> form.owner|as_crispy_field </div>% endif % 我正在对现有系统进行更改,所以我不写那部分哈哈。感谢你的帮助!它有效!

以上是关于在 django View 类中访问表单“字段”的主要内容,如果未能解决你的问题,请参考以下文章

在 django 视图中将表单字段作为属性访问

Django 访问不属于表单的字段

Django表单字段汇总

在 Django 中禁用所有表单字段的语法

使用请求对象访问 django 视图中的 html 表单字段

访问模板化 Django 中的表单字段属性