1

我有 ProjectForm 表单,其中一个字段是 ModelChoiceField,外键是 Company Model。创建新记录并保存不是问题,但是当我想编辑该记录时,此字段为空(例如,如果未选择任何公司,但在 DB 中我可以通过正确的选择看到它),其他字段已正确填写。

我想尽可能避免更改模板代码,以便由通用表单模板生成。

----- 模型.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)

----- 模板.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>

----- 数据库截图 -----

数据库截图

----- 表格截图 ----- (首先输入的是公司)

在此处输入图像描述

4

2 回答 2

1

initial=obj.__dict__将返回project字典

{
  ...
  company_id: value
} 

在您的表单中,您定义了字段名称company。因此,您需要initial使用与 相同的值更新表单company_id,从而company正确填充该字段

{
  company: value
}

使用model_to_dict可以显式删除不可编辑的字段,检查并获取外键的 id,你可以阅读更多关于它的来源,因为没有很好的文档记录。

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))
于 2020-06-28T20:02:52.377 回答
0

根据@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']

或者

----- 意见.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))
    ...
于 2020-06-28T20:22:11.320 回答