2010-11-09 29 views
10

我有一個外鍵關聯的兩種型號:自由格式輸入一個Django的ModelForm

# models.py  
class TestSource(models.Model): 
    name  = models.CharField(max_length=100) 

class TestModel(models.Model): 
    name  = models.CharField(max_length=100) 
    attribution = models.ForeignKey(TestSource, null=True) 

默認情況下,一個Django的ModelForm將呈現此作爲<select><option>秒;但是我寧願將這個函數作爲一個自由格式輸入,<input type="text"/>,並在後臺獲取或創建必要的TestSource對象,然後將其與TestModel對象相關聯。

我試圖定義一個定製的ModelForm和外地來實現:

# forms.py 
class TestField(forms.TextInput): 
    def to_python(self, value): 
    return TestSource.objects.get_or_create(name=value) 

class TestForm(ModelForm): 
    class Meta: 
    model=TestModel 
    widgets = { 
     'attribution' : TestField(attrs={'maxlength':'100'}), 
    } 

不幸的是,我得到:invalid literal for int() with base 10: 'test3'試圖籤is_valid提交的表單上時。我哪裏錯了?他們更簡單的方法來實現這一目標嗎?

回答

11

像這樣的東西應該工作:

class TestForm(ModelForm): 
    attribution = forms.CharField(max_length=100) 

    def save(self, commit=True): 
     attribution_name = self.cleaned_data['attribution'] 
     attribution = TestSource.objects.get_or_create(name=attribution_name)[0] # returns (instance, <created?-boolean>) 
     self.instance.attribution = attribution 

     return super(TestForm, self).save(commit) 

    class Meta: 
    model=TestModel 
    exclude = ('attribution') 
+0

這有很大幫助。但我仍然有一些問題,視圖中是否需要任何非標準代碼?我的is_valid()檢查依然爆炸:無法分配「u'myString'」:「TestModel.attribution」必須是「TestSource」實例。 – brown145 2010-11-09 21:06:56

+1

@ brown145:我認爲你必須排除該屬性,否則它會嘗試驗證它。看到我更新的答案。 – sdolan 2010-11-09 21:25:56

1

這裏有幾個問題。

首先,您定義了一個字段,而不是一個小部件,因此您不能在widgets字典中使用它。您需要覆蓋表單頂層的字段聲明。

其次get_or_create返回兩個值:檢索或創建的對象,以及顯示是否創建它的布爾值。您真的只想從to_python方法中返回這些值中的第一個。

我不確定這些是否會導致您的實際錯誤。你需要發佈我們確切的實際回溯。

0

TestForm.attribution預計int值 - 關鍵TestSource模型。

也許這個版本的車型會更方便您:

class TestSource(models.Model): 
    name = models.CharField(max_length=100, primary_key=True)