我只是寫場和Widget子類,它們可以解決這個特殊的問題,並且可以和JS自動完成一起使用,並且可以重用。不過,它需要比解決方案更多的工作,而且我不確定是否要使用我的解決方案。無論哪種方式 - 我希望我會得到一些upvotes - 我花了相當長的一段時間和精力寫這...
相反的定義就像你你的ModelForm沒有與clean_
搞亂我建議這樣的事情:
class SongForm(forms.ModelForm):
artist = CustomModelChoiceField(queryset = Artist.objects.all(), query_field = "name")
class Meta:
model = Song
現在,CustomModelChoiceField(我想不出更好的名稱)是ModelChoiceField的子類,這很好,因爲我們可以使用queryset
參數來縮小可接受的選擇範圍。如果widget
參數不存在(如上所述),則會使用此字段的默認值(稍後會詳細介紹)。 query_field
是可選的,默認爲"pk"
。所以,這裏是域代碼:
class CustomModelChoiceField(forms.ModelChoiceField):
def __init__(self, queryset, query_field = "pk", **kwargs):
if "widget" not in kwargs:
kwargs["widget"] = ModelTextInput(model_class = queryset.model, query_field = query_field)
super(CustomModelChoiceField, self).__init__(queryset, **kwargs)
def to_python(self, value):
try:
int(value)
except:
from django.core.exceptions import ValidationError
raise ValidationError(self.error_messages['invalid_choice'])
return super(CustomModelChoiceField, self).to_python(value)
什麼身體__init__
手段是創造CustomModelChoiceField
過程中設置widget = None
給了我們普通ModelChoiceField
(這是非常有益的,而調試...)。現在,實際的工作在ModelTextInput
部件進行:
class ModelTextInput(forms.TextInput):
def __init__(self, model_class, query_field, attrs = None ):
self.model_class = model_class
self.query_field = query_field
super(ModelTextInput, self).__init__(attrs)
def render(self, name, value, attrs = None):
try:
obj = self.model_class.objects.get(pk = value)
value = getattr(obj, self.query_field)
except:
pass
return super(ModelTextInput, self).render(name, value, attrs)
def value_from_datadict(self, data, files, name):
try:
return self.model_class.objects.get(**{ self.query_field : data[name] }).id
except:
return data[name]
它本質的TextInput,就是知道的兩個額外的東西 - 這模型它代表哪個屬性。 (model_class
應替換爲queryset
,以便將實際可能的選擇縮小至實際工作狀態,稍後我會予以修復)。查看value_from_datadict
的實現,很容易發現爲什麼to_python
必須被重寫 - 它期望值爲int
,但不檢查它是否爲真 - 並僅將值傳遞給關聯的模型,該模型因醜陋的異常而失敗。
我測試了這一段時間,它的工作原理 - 你可以指定由形成場會嘗試不同的模型領域找到自己的artist
,形狀誤差處理是由基類自動完成的,不需要編寫自定義的clean_
方法每次你想使用類似的功能。
我現在太累了,但我會盡力編輯明天的這篇文章(和代碼)。
還沒有試過,但看起來很有趣 – juanefren 2010-07-26 23:33:00