为什么我的 Django 模板不呈现 ModelForm 的 id 或 pk 字段?

Al *_*art 2 forms django django-templates

在 Django 1.10 中,我使用数据库中的记录在模板中预填充 ModelForm,以便在表单中编辑该记录。但是,当我想为表单呈现 HTML 时,它不显示id(或pk)字段。我想把 id 放在一个隐藏的 <input> 标签中,这样当表单提交时,后端知道提交表单时要编辑哪条记录。我的网络应用程序在 URL 中没有 id。

这是我的models.py:

from django.db import models

class MyModel(models.Model):
    name = models.CharField(max_length=50)
    phone = models.CharField(max_length=50)
Run Code Online (Sandbox Code Playgroud)

在数据库中,我添加了一条带有 name'Alice'和 phone 的MyModel 记录'212-555-5555'。id/主键是1.

这是我的forms.py:

from django import forms
from . import models

class TestForm(forms.ModelForm):
    class Meta:
        model = models.MyModel
        fields = ['id', 'name', 'phone']
Run Code Online (Sandbox Code Playgroud)

这是我的views.py:

from django.shortcuts import render
from . import forms, models

def test_page(request):
    m = models.MyModel.objects.get(name='Alice')
    prepopulatedForm = forms.TestForm(instance=m)
    return render(request, 'testproject/test_template.html', {'form': prepopulatedForm})
Run Code Online (Sandbox Code Playgroud)

这是我的 test_template.html:

<h1>Test Page</h1>
{{ form }}
Run Code Online (Sandbox Code Playgroud)

这会在页面上呈现表单,并预先填充'Alice''212-555-5555'

<h1>Test Page</h1>
<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" maxlength="50" name="name" type="text" value="Alice" required /></td></tr>
<tr><th><label for="id_phone">Phone:</label></th><td><input id="id_phone" maxlength="50" name="phone" type="text" value="212-555-5555" required /></td></tr>
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么 id/primary key 列没有出现在这个表单中?当我将它用于模板时,我也无法渲染它:

<h1>Test Page</h1>
{{ form.id }}
{{ form.name }}
{{ form.phone }}
Run Code Online (Sandbox Code Playgroud)

这会呈现一个空白,其中 id <input> 应该是:

<h1>Test Page</h1>

<input id="id_name" maxlength="50" name="name" type="text" value="Alice" required />
<input id="id_phone" maxlength="50" name="phone" type="text" value="212-555-5555" required />
Run Code Online (Sandbox Code Playgroud)

我可以从运行python manage.py shell中看到记录实际上在那里:

>>> from testproject import models
>>> m = models.MyModel.objects.get(name='Alice')
>>> m.id
1
Run Code Online (Sandbox Code Playgroud)

在 forms.py 中,设置fields['id', 'name', 'phone']不会导致任何错误,['pk', 'name', 'phone']. 但是,如果我故意添加一个不存在的字段名称,例如['NOT_REAL_FIELD', 'name', 'phone']python manage.py runserver则会产生错误:

  File "C:\Users\Al\venvs\tas_env\lib\site-packages\django\forms\models.py", line 257, in __new__
    raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (NOT_REAL_FIELD) specified for MyModel
Run Code Online (Sandbox Code Playgroud)

所以我知道'id'/'pk'必须是放在 ModelForm 中的合法字段。

为什么我的 Django 模板不呈现 ModelForm 的 id 或 pk 字段?

最后,我想将主键作为隐藏输入包含在表单中,以便可以编辑数据库中的记录。另请注意,我不关心 ModelAdmin,因为我试图在用户可见的模板中显示它,而不是在管理面板中。pk是只读的就好了;它只需要在模板中呈现。

scu*_*rda 5

如何访问 id 使用{{ form.initial.id }}

从我在查看 ModelForm 元类时可以看出,form.initial填充与创建表单属性(例如form.nameform.phone)略有不同。所以基本上它是在django元类魔法的杂草中......

更具体一点。似乎在创建表单时,model_to_dict被调用从传入的模型实例中提取数据。但直到fields_for_model被调用,表单实例才具有可作为类属性访问的模型字段。我猜想这id以某种方式被排除在fields_for_model. 看起来您引用的不可编辑字段异常也在此处引发。


Dan*_*man 3

id字段自动具有editable=False,这意味着默认情况下它不会显示在任何模型表单中。

不过,无需将 id 放入隐藏字段中。如果您转到某个 URL 来编辑对象,并且该 URL 显示一个表单,则它应该提交回同一 URL - 在这种情况下,您仍然在 URL 中拥有该 id。