我在Django中使用ModelForm
爲我的數據庫中的模型構建了一個編輯表單。表單中的每個字段都是可選的,因爲用戶可能只想編輯一個字段。ModelForm在模型數據上保存空字段
我遇到的問題是,當我在查看通話save()
,任何空字段被保存在實例的原始值(例如,如果我只輸入一個新first_name
,則last_name
和ecf_code
領域將節省一個空字符串在相應的實例)
形式:
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 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(),
}
)
我試着重寫表格的save()
方法來明確地檢查哪些字段在POST
請求中有值,但這似乎也沒有任何區別。
嘗試在重寫保存方法:
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
我也沒有對Player
模型的任何默認值,文檔說的ModeForm
將使用這些在表單提交缺席值。
編輯:
這裏是整個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
編輯:
好了,所以這裏是解決方案,我想我把它放在這裏,因爲它可能是有用的其他人(我肯定從中學到了一點)。
因此,事實證明,模型表單的is_valid()
方法實際上會更改您傳遞到表單的實例,爲save()
方法保存它們做好準備。因此,爲了解決這個問題,我伸出形式的clean()
方法:
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
這基本上只是檢查是否字段爲空,如果一個字段爲空,從現有的值填充給定實例。在使用新表單值設置實例變量之前調用clean()
,這樣,任何空字段實際上都會填充相應的現有實例數據。
非常感謝您的幫助!我把它放到窗體的save()方法中,但是它仍然不起作用,如果我在窗體的save方法開始時打印實例的變量,它們已經被設置爲空的字符串值'instance.save()'甚至在窗體的方法中調用(希望是有道理的) – RHSmith159
@ RHSmith159對不起,這不是幫助你,你可以添加表單'EditPlayerForm'的問題? – PRMoureu
肯定的事情,我現在將它添加 – RHSmith159