我正在使用脆性表格让用户创建新的问题帖子,但我希望用户不要更改“项目”字段,以便可以将问题放在正确的项目下。我使用了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 %}
答案 0 :(得分:3)
将值设置为 readonly 还不够。这只会影响HTML的呈现方式。根据这种情况下浏览器的工作,用户可能仍可以编辑表单字段。
但是,即使用户无法编辑表单,对HTTP请求的工作方式有所了解的人仍然可以恶意地在请求中输入值,因此更改了数据库中不应获取的值改变了。
自djang-1.9起,您可以更改表单上的.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)
请注意,您可能需要一些initial
或instance
,因为否则,将没有任何数据可回退。
在上面的代码片段中,我们两次编写了相同的表达式:每次构造表单时。这违反了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')
答案 1 :(得分:0)
可能使该字段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"