2017-03-28 1 views
1

In Django 1.10 fülle ich eine ModelForm in einer Vorlage mit einem Datensatz aus der Datenbank aus, um diesen Datensatz im Formular zu bearbeiten. Wenn ich das HTML für das Formular jedoch wiedergeben möchte, zeigt es die id (oder pk) Felder nicht an. Ich möchte die ID in einen versteckten < Eingang setzen, also, wenn das Formular übermittelt das Back-End weiß, welcher Datensatz zu bearbeiten, wenn das Formular übermittelt wird. Meine Webanwendung hat keine ID in der URL.Warum rendert meine Django-Vorlage nicht das ID- oder PK-Feld eines ModelForms?

Hier ist meine models.py:

from django.db import models 

class MyModel(models.Model): 
    name = models.CharField(max_length=50) 
    phone = models.CharField(max_length=50) 

In der Datenbank habe ich einen MyModel Datensatz mit Namen 'Alice' und Telefon '212-555-5555' hinzugefügt. Der ID/Primärschlüssel ist 1.

Hier ist meine forms.py:

from django import forms 
from . import models 

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

Hier mein views.py ist:

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}) 

Hier ist meine test_template.html:

<h1>Test Page</h1> 
{{ form }} 

Dies macht die Form auf der Seite mit 'Alice' und '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> 

Meine Frage ist, warum erscheint die ID/Primärschlüsselspalte nicht in dieser Form? Ich kann es nicht bekommen zu machen, wenn ich dies für die Vorlage verwenden entweder:

<h1>Test Page</h1> 
{{ form.id }} 
{{ form.name }} 
{{ form.phone }} 

Dies macht eine leere, wo die ID <Eingang> sein sollte:

<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 /> 

ich sehen kann python manage.py shell vom Laufen dass der Datensatz in der Tat gibt es:

>>> from testproject import models 
>>> m = models.MyModel.objects.get(name='Alice') 
>>> m.id 
1 

in forms.py, das Setzen von fields-['id', 'name', 'phone'] nicht ein verursachen y Fehler, noch ['pk', 'name', 'phone']. Wenn ich jedoch ein nicht vorhandenen Feldnamen wie ['NOT_REAL_FIELD', 'name', 'phone'] gezielt hinzufügen, dann wird python manage.py runserver einen Fehler erzeugen:

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 

Also ich weiß, dass 'id'/'pk' ein legitimes Feld in der Modelform zu bringen sein muss.

Warum rendert meine Django-Vorlage nicht das ID- oder PK-Feld von ModelForm?

Schließlich möchte ich den Primärschlüssel als versteckte Eingabe in das Formular aufnehmen, so dass der Datensatz in der Datenbank bearbeitet werden kann. Beachten Sie auch, dass ModelAdmin nicht wichtig ist, da ich versuche, dies in einer Vorlage anzuzeigen, die für Benutzer sichtbar ist, nicht im Admin-Steuerfeld. Es ist in Ordnung, dass der PK schreibgeschützt ist. es muss nur in der Vorlage gerendert werden.

+0

Warum soll das ID-Feld bearbeitbar sein? In Django besteht der übliche Ansatz darin, die ID in die URL aufzunehmen, z. '/ mymodel/ /', rufen Sie dann das zu bearbeitende Objekt in der Ansicht z. 'MyModel.objects.get (pk = pk)'. – Alasdair

+0

Ich möchte die PK in eine versteckte < Eingabe einfügen > Tag, so wenn das Formular übermittelt das Back-End weiß, welcher Datensatz zu bearbeiten, wenn das Formular übergeben wird. Meine URLs haben nicht den pk von , sondern sind eher "/ /". Muss ich diese zwei Bits von Informationen verwenden, um den Datensatz abzurufen? –

Antwort

1

Das Feld id hat automatisch editable=False, was bedeutet, dass es standardmäßig in keiner Modellform angezeigt wird.

Es ist jedoch nicht notwendig, die ID in ein verstecktes Feld zu setzen. Wenn Sie zu einer URL gehen, um ein Objekt zu bearbeiten, und diese URL ein Formular anzeigt, sollte sie an die gleiche URL zurückgesendet werden. In diesem Fall haben Sie immer noch die ID in der URL.

+0

Ich glaube nicht, dass das so ist. Wenn ich 'editable = False' auf die Felder 'name' oder' phone' setze, erhalte ich eine Fehlermeldung, sobald ich 'python manage.py runserver': ' django.core.exceptions.FieldError: 'phone 'kann nicht für das MyModel-Modellformular angegeben werden, da es sich um ein nicht bearbeitbares Feld handelt' Ich erhalte diesen Fehler nicht mit den Feldern 'id' oder 'pk'. –

+0

In meiner Webanwendung verwende ich nicht den Primärschlüssel in URL. Die URL ist//, anstatt die ID des Benutzers zu verwenden, also ist es nicht möglich, sie von der URL zu bekommen. –

2

Wie wäre es mit dem Zugriff auf die ID mit {{ form.initial.id }}?

Von dem, was ich beim Betrachten der ModelForm-Metaklasse feststellen kann, ist form.initial etwas anders als die Erstellung von Formulareigenschaften (z. B. form.name oder form.phone) ausgefüllt. Also im Grunde ist es in den Unkräutern der Django Metaklasse magic ...

Um ein bisschen genauer zu sein. Es sieht so aus, als ob beim Erstellen eines Formulars model_to_dict aufgerufen wird, um Daten aus der übergebenen Modellinstanz zu ziehen. Erst wenn die Instanz fields_for_model aufgerufen wird, stehen der Modellinstanz die Modellfelder als Klassenattribute zur Verfügung. Ich würde vermuten, dass id irgendwie von den Feldern ausgeschlossen wird, die in fields_for_model betrachtet werden. Es sieht so aus, als ob die nicht editierbare Feldausnahme, auf die Sie verwiesen haben, hier ebenfalls angesprochen wird.

+0

Das funktioniert! Seltsamerweise ist '{{form.initial.pk}}' leer. Obwohl dies meine ursprüngliche Frage nicht beantwortet, ist es eine etwas bessere Problemumgehung als meine aktuelle Problemumgehung. Was google ich, um herauszufinden, was ".initial" ist? Handelt es sich um "dynamische Anfangswerte" oder ist es ein anderes Konzept? Ich würde gerne herausfinden, was die beste Vorgehensweise für das Rendern eines PK in einer Vorlage ist. –

+0

Nur eine Berührung hinzugefügt mehr Info. Ich konnte durch den Quellcode von ModelForm, insbesondere den Metaklassenabschnitt, einen groben Sinn erkennen. – scuerda

Verwandte Themen