Ich erstelle ein Bearbeitungsformular für ein Modell in meiner Datenbank mit einem ModelForm
in Django. Jedes Feld im Formular ist optional, da der Benutzer möglicherweise nur ein Feld bearbeiten möchte.ModelForm Modelldaten mit leeren Feldern speichern
Das Problem, das ich habe, ist, dass, wenn ich save()
in der Ansicht aufrufen, werden alle leeren Felder über die ursprünglichen Werte der Instanz gespeichert werden (zB wenn ich nur einen neuen first_name
eingeben, die last_name
und ecf_code
Felder eine leere Zeichenfolge speichern in dem entsprechenden Beispiel)
die Form:.
class EditPlayerForm(forms.ModelForm):
class Meta:
model = Player
fields = ['first_name', 'last_name', 'ecf_code']
def __init__(self, *args, **kwargs):
super(EditPlayerForm, self).__init__(*args, **kwargs)
self.fields['first_name'].required = False
self.fields['last_name'].required = False
self.fields['ecf_code'].required = False
die Ansicht:
def view(request, player_pk = ''):
edit_player_form = forms.EditPlayerForm(auto_id="edit_%s")
if "edit_player_form" in request.POST:
if not player_pk:
messages.error(request, "No player pk given.")
else:
try:
selected_player = Player.objects.get(pk = player_pk)
except Player.DoesNotExist:
messages.error(request, "The selected player could not be found in the database.")
return redirect("players:management")
else:
edit_player_form = forms.EditPlayerForm(
request.POST,
instance = selected_player
)
if edit_player_form.is_valid():
player = edit_player_form.save()
messages.success(request, "The changes were made successfully.")
return redirect("players:management")
else:
form_errors.convert_form_errors_to_messages(edit_player_form, request)
return render(
request,
"players/playerManagement.html",
{
"edit_player_form": edit_player_form,
"players": Player.objects.all(),
}
)
Ich habe versucht, die save()
Methode des Formulars zu überschreiben, um explizit zu überprüfen, welche Felder Werte in der POST
Anfrage haben, aber das schien auch keinen Unterschied zu machen.
Versuch, die Speichermethode bei Überschreiben:
def save(self, commit = True):
# Tried this way to get instance as well
# instance = super(EditPlayerForm, self).save(commit = False)
self.cleaned_data = dict([ (k,v) for k,v in self.cleaned_data.items() if v != "" ])
try:
self.instance.first_name = self.cleaned_data["first_name"]
except KeyError:
pass
try:
self.instance.last_name = self.cleaned_data["last_name"]
except KeyError:
pass
try:
self.instance.ecf_code = self.cleaned_data["ecf_code"]
except KeyError:
pass
if commit:
self.instance.save()
return self.instance
ich auch haben keine Standardwerte für das Player
Modell wie die Docs sagen die ModeForm
diese für Werte fehlen in Form Vorlage verwenden.
EDIT:
Hier ist die ganze EditPlayerForm
:
class EditPlayerForm(forms.ModelForm):
class Meta:
model = Player
fields = ['first_name', 'last_name', 'ecf_code']
def __init__(self, *args, **kwargs):
super(EditPlayerForm, self).__init__(*args, **kwargs)
self.fields['first_name'].required = False
self.fields['last_name'].required = False
self.fields['ecf_code'].required = False
def save(self, commit = True):
# If I print instance variables here they've already
# been updated with the form values
self.cleaned_data = [ k for k,v in self.cleaned_data.items() if v ]
self.instance.save(update_fields = self.cleaned_data)
if commit:
self.instance.save()
return self.instance
EDIT:
Ok, so ist hier die Lösung, ich dachte ich es würde hier, wie es nützlich sein könnte, andere Leute (ich habe sicherlich ein bisschen davon gelernt).
So stellt sich heraus, dass die is_valid()
Methode des Modells Formular tatsächlich die Änderungen an der Instanz, die Sie in das Formular übergeben, bereit für die save()
Methode, um sie zu speichern. Also, um dieses Problem zu beheben, ich verlängerte die clean()
Methode des Formulars:
def clean(self):
if not self.cleaned_data.get("first_name"):
self.cleaned_data["first_name"] = self.instance.first_name
if not self.cleaned_data.get("last_name"):
self.cleaned_data["last_name"] = self.instance.last_name
if not self.cleaned_data.get("ecf_code"):
self.cleaned_data["ecf_code"] = self.instance.ecf_code
Diese im Grunde prüft nur um zu sehen, wenn die Felder leer sind und wenn ein Feld leer ist, füllen Sie es mit dem vorhandenen Wert aus dem gegebene Instanz. clean()
wird aufgerufen, bevor die Instanzvariablen mit den neuen Formularwerten festgelegt werden. Auf diese Weise wurden alle leeren Felder tatsächlich mit den entsprechenden vorhandenen Instanzdaten gefüllt.
Vielen Dank für die Hilfe! Ich habe dies in die 'save()' Methode des Formulars eingefügt, aber es funktioniert immer noch nicht, wenn ich die Variablen der Instanz am Anfang der Speichermethode im Formular drucke, wurden sie bereits auf die leeren Zeichenkettenwerte gesetzt 'instance.save()' wird sogar in der Methode des Formulars aufgerufen (hoffe, dass das Sinn ergab) – RHSmith159
@ RHSmith159 Sorry, das half dir nicht, könntest du das Formular 'EditPlayerForm' zu der Frage hinzufügen? – PRMoureu
sicher, ich füge es jetzt – RHSmith159