Django ModelChoiceField 编辑时未填写
Django ModelChoiceField is not filled when editing
我有一个 ProjectForm 表单,其中一个字段是带有公司模型外键的 ModelChoiceField。创建新记录并保存不是问题,但是当我想编辑该记录时,这个字段是空的(比如如果选择了 none 公司,但在数据库中我可以通过正确的选择看到它),其他字段被填充正确。
我想尽可能避免更改模板代码,因此它由通用表单模板生成。
-----models.py-----
class Company(models.Model):
name = models.CharField(max_length=250, unique=True)
...
class Project(models.Model):
company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=250, blank=False)
description = models.TextField()
...
-----forms.py-----
@parsleyfy
class ProjectForm(forms.Form):
company = forms.ModelChoiceField(label='Společnost', queryset=Company.objects.all(), required=False)
name = forms.CharField(label='Název')
...
-----view.py-----
def edit(request, pk):
context = {'form_url': reverse('projects:project-edit', args=(pk,)),
'form_type':'edit'}
obj = get_object_or_404(Project, pk=pk)
if request.method == "GET":
form = ProjectForm(initial=obj.__dict__)
else:
form = ProjectForm(request.POST, request.FILES)
if form.is_valid():
try:
obj.update(**form.cleaned_data)
except IntegrityError:
errors = form._errors.setdefault("name", ErrorList())
errors.append(u"Toto jméno již existuje")
else:
return redirect(LIST_URL) # SUCCESSFULLY SAVED
context['form'] = form
return render(request, FORM_TEMPLATE, context)
-----template.html-----
<form role="form" action="{{ form_url }}" method="post" enctype="multipart/form-data"
data-parsley-validate novalidate>
{% include 'projects/reusable/form_template.html' %}
</form>
in which:
{% elif field|input_type == 'Select' %}
<div for="{{ field.label }}" class="col-sm-2 col-form-label">
{{ field.label_tag }}
</div>
<div class="col-sm-10">
{{ field|add_classes:'form-control'}}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
-----数据库截图-----
----- 表格截图-----(第一个输入是公司)
initial=obj.__dict__
将 return project
字典与
{
...
company_id: value
}
在您的表单中,您将字段名称定义为 company
。因此,您需要使用与 company_id
相同的值更新您的表单 initial
,这样 company
字段将被正确填充
{
company: value
}
使用 model_to_dict
可以显式删除不可编辑的字段,检查并获取外键的 ids,你可以阅读更多关于它的源代码,因为没有很好的文档.
def model_to_dict(instance, fields=None, exclude=None):
"""
Return a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.
"""
pass
from django.forms.models import model_to_dict
# model_to_dict will handle 'special' fields properly
form = ProjectForm(initial=model_to_dict(obj))
根据@minglyu回答,我添加了代码解决方案
-----forms.py-----
@parsleyfy
class ProjectForm(forms.Form):
company = forms.ModelChoiceField(label='Společnost', queryset=Company.objects.all(), required=False)
name = forms.CharField(label='Název')
...
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if 'initial' in kwargs.keys():
self.initial['company'] = kwargs['initial']['company_id']
或
-----views.py-----
from django.forms import models
...
def edit(request, pk):
...
obj = get_object_or_404(Project, pk=pk)
if request.method == "GET":
form = ProjectForm(initial=models.model_to_dict(obj))
...
我有一个 ProjectForm 表单,其中一个字段是带有公司模型外键的 ModelChoiceField。创建新记录并保存不是问题,但是当我想编辑该记录时,这个字段是空的(比如如果选择了 none 公司,但在数据库中我可以通过正确的选择看到它),其他字段被填充正确。
我想尽可能避免更改模板代码,因此它由通用表单模板生成。
-----models.py-----
class Company(models.Model):
name = models.CharField(max_length=250, unique=True)
...
class Project(models.Model):
company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=250, blank=False)
description = models.TextField()
...
-----forms.py-----
@parsleyfy
class ProjectForm(forms.Form):
company = forms.ModelChoiceField(label='Společnost', queryset=Company.objects.all(), required=False)
name = forms.CharField(label='Název')
...
-----view.py-----
def edit(request, pk):
context = {'form_url': reverse('projects:project-edit', args=(pk,)),
'form_type':'edit'}
obj = get_object_or_404(Project, pk=pk)
if request.method == "GET":
form = ProjectForm(initial=obj.__dict__)
else:
form = ProjectForm(request.POST, request.FILES)
if form.is_valid():
try:
obj.update(**form.cleaned_data)
except IntegrityError:
errors = form._errors.setdefault("name", ErrorList())
errors.append(u"Toto jméno již existuje")
else:
return redirect(LIST_URL) # SUCCESSFULLY SAVED
context['form'] = form
return render(request, FORM_TEMPLATE, context)
-----template.html-----
<form role="form" action="{{ form_url }}" method="post" enctype="multipart/form-data"
data-parsley-validate novalidate>
{% include 'projects/reusable/form_template.html' %}
</form>
in which:
{% elif field|input_type == 'Select' %}
<div for="{{ field.label }}" class="col-sm-2 col-form-label">
{{ field.label_tag }}
</div>
<div class="col-sm-10">
{{ field|add_classes:'form-control'}}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
-----数据库截图-----
----- 表格截图-----(第一个输入是公司)
initial=obj.__dict__
将 return project
字典与
{
...
company_id: value
}
在您的表单中,您将字段名称定义为 company
。因此,您需要使用与 company_id
相同的值更新您的表单 initial
,这样 company
字段将被正确填充
{
company: value
}
使用 model_to_dict
可以显式删除不可编辑的字段,检查并获取外键的 ids,你可以阅读更多关于它的源代码,因为没有很好的文档.
def model_to_dict(instance, fields=None, exclude=None):
"""
Return a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.
"""
pass
from django.forms.models import model_to_dict
# model_to_dict will handle 'special' fields properly
form = ProjectForm(initial=model_to_dict(obj))
根据@minglyu回答,我添加了代码解决方案
-----forms.py-----
@parsleyfy
class ProjectForm(forms.Form):
company = forms.ModelChoiceField(label='Společnost', queryset=Company.objects.all(), required=False)
name = forms.CharField(label='Název')
...
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if 'initial' in kwargs.keys():
self.initial['company'] = kwargs['initial']['company_id']
或
-----views.py-----
from django.forms import models
...
def edit(request, pk):
...
obj = get_object_or_404(Project, pk=pk)
if request.method == "GET":
form = ProjectForm(initial=models.model_to_dict(obj))
...