【问题标题】:How to disable a field in crispy form django如何以清脆的形式禁用 django 中的字段
【发布时间】:2018-11-28 18:10:03
【问题描述】:

我正在使用清晰的表单让用户创建一个新的问题帖子,但我希望用户不要更改“项目”字段,以便问题可以放在正确的项目下。我用了form.fields['project'].widget.attrs['readonly'] = True,但这个只有样式禁用效果,没有真正的功能。

models.py

def new_issue(request, project_id):
    if request.method == 'POST':
        form = IssueForm(request.POST)
        if form.is_valid():
            issue = form.save(commit=False)
            issue.author = request.user
            issue.save()
            return redirect('project:issue_tracker:issue_detail',project_id=project_id,issue_id=issue.id)
    else:
        form = IssueForm(initial={'project': project_id})
        form.fields['project'].widget.attrs['readonly'] = True
    template = 'issue_tracker/issue/new_issue.html'
    context = {'form': form,'project_id':project_id}
    return render(request, template, context)

form.py

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('body',)

class IssueForm(forms.ModelForm):
    class Meta:
        model = Issue
        fields = ('title','content','project','status')

class NewIssueForm(forms.ModelForm):
    class Meta:
        model = Issue
        fields = ('title','content','project','status')

new_issue.html

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}
    <h1>Add New Issue </h1>
    <form method="POST" class="Issue-form">{% csrf_token %}
        {{form|crispy}}
        <button type="submit" class="btn btn-success">Submit</button>
    </form>

{% endblock %}

【问题讨论】:

  • 你使用 Django-1.9 或更高版本吗?

标签: python django forms


【解决方案1】:

将值设置为 readonly不够 的。这只会影响 HTML 的呈现方式。根据浏览器在这种情况下所做的事情,用户仍然可以编辑表单字段。

但是,即使用户不能编辑表单,对 HTTP 请求如何工作有一定了解的人仍然可以在请求中恶意输入值,从而更改数据库中不应该获取的值改变了。

及以上

由于,您可以更改表单上的.disabled 属性。在这种情况下,这不仅会将该字段呈现为禁用或只读状态,还会防止有人恶意输入值。如果用户输入一些数据,则该数据将被忽略(对于该特定字段)。所以我们可以这样写:

def new_issue(request, project_id):
    if request.method == 'POST':
        form = IssueForm(request.POST, initial={'project': project_id})
        form.fields['project'].disabled = True
        if form.is_valid():
            issue = form.save(commit=False)
            issue.author = request.user
            issue.save()
            return redirect('project:issue_tracker:issue_detail',project_id=project_id,issue_id=issue.id)
    else:
        form = IssueForm(initial={'project': project_id})        
        form.fields['project'].disabled = True
    template = 'issue_tracker/issue/new_issue.html'
    context = {'form': form,'project_id':project_id}
    return render(request, template, context)

请注意,您可能需要一些initialinstance,否则,根本没有数据可供后备。

将其移入表单

在上面的代码片段中,我们写了两次相同的表达式:每次我们构造一个表单。这违反了 DRY 原则。通常您指定该字段,或者 - 例如,在该字段并非始终禁用的情况下,您可以通过覆盖 __init__ 构造函数来指定它。

例如:

class IssueForm(forms.ModelForm):

    def __int__(self, *args, disabled_project=True, **kwargs):
        super(IssueForm, self).__init__(*args, **kwargs)
        self.fields['project'].disabled = disabled_project

    class Meta:
        model = Issue
        fields = ('title','content','project','status')

所以现在我们可以使用一个参数来初始化IssueForm,并指定disabled_project标志是True还是False

及以下

如果您使用 Django 版本(不推荐,因为不再支持),我们仍然可以通过添加clean_somefield 函数来确保忽略数据。例如:

class IssueForm(forms.ModelForm):

    def __int__(self, *args, **kwargs):
        super(IssueForm, self).__init__(*args, **kwargs)
        widget = self.fields['project'].widget
        widget.attrs['readonly'] = widget.attrs['disabled'] = widget.disabled = True

    def clean_project(self):
        return self.instance.project

    class Meta:
        model = Issue
        fields = ('title','content','project','status')

【讨论】:

  • 很高兴知道:)
  • 这真是太棒了!!效果很好!!
  • 谢谢,这帮助很大。与“只读”斗争了一段时间,但你的答案是金。
【解决方案2】:

可能使该字段readonly 会有所帮助:

class NewIssueForm(forms.ModelForm):
    class Meta:
        model = Issue
        fields = ('content','project','status')

    title= forms.CharField(widget=forms.TextInput(attrs={ 'id': 'title',
                                                          'readonly':'readonly'}))

在您看来,您需要使用原始值预填充标题字段,如下所示:

   some_form = NewIssueForm()        
   some_form.fields['title'].initial = "some_title"

【讨论】:

    猜你喜欢
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 2018-01-16
    • 2012-12-06
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    相关资源
    最近更新 更多