2013-07-08 79 views
1

我正在學習django表單,並想知道如何使模型表單生成顯示只。Django ModelForm-如何使表單生成不可編輯

models.py

class Person(models.Model): 
    first_name = models.CharField(max_length=40, null=True) 
    last_name = models.CharField(max_length=40, null=True) 
    #more fields 

forms.py

class PersonForm(ModelForm): 
    class Meta: 
     model = Person 

要生成與數據庫中的一些現有數據格式:

person=Person.objects.get(id=someid) 
person_form = PersonForm(instance = person) 

所有領域在形式中在頁面中可編輯。但是,我只想顯示數據。

經過一番在StackOverflow搜索後,我發現了一個類似的解決方案how to show a django ModelForm field as uneditable,它教導瞭如何設置個別字段不可知。

但我想使整個表格不可編輯。有沒有更好的方法來做到這一點,而不是將所有的字段一一設置爲不可編輯?

非常感謝您的幫助。

更新:我發現流動的代碼有助於使窗體不可編輯,但仍不確定這是否是正確的方式。

for field in person_form.fields: 
      person_form.fields[field].widget.attrs['readonly'] = True 

謝謝你的建議。

+1

這將是做到這一點的方式,因爲Django沒有內置的小部件。 –

+0

你的意思是我的更新中的方法? – Mona

+0

@limelights是的,它與我的模型中的大多數字段都可以正常工作,但在我的模型中有CountryField,似乎將'readonly'設置爲True對CountryField不起作用,它仍然可以在頁面中進行編輯。有什麼建議嗎? – Mona

回答

0

另一種解決方案或許,不必做任何處理,只顯示這樣的..

<table border='1'> 
    {% for field in form%} 
     <tr> 
      <td>{{field.label}}</td> 
      <td>{{field.value}}</td> 
     </tr> 

    {% endfor%} 

</table> 
1

沒有屬性叫做editable或類似的形式可以在所有的領域作用。所以,你不能在表單層面上做到這一點。

此外,django表單中使用的Field類也沒有這樣的屬性,所以不可能設置這樣的屬性並使字段只讀。因此,您必須在表單的__init__表單的字段中進行操作。

class PersonForm(ModelForm): 
    class Meta: 
     model = Person 

    def __init__(self, *args, **kwargs): 
     super(PersonForm, self).__init__(*args, **kwargs) 
     for name, field in self.fields.iteritems(): 
      field.widget.attrs['readonly'] = 'true' 

如果您只想使某些字段不可編輯,請更改__init__

def __init__(self, *args, **kwargs): 
     super(PersonForm, self).__init__(*args, **kwargs) 
     uneditable_fields = ['first_name', 'last_name'] 
     for field in uneditable_fields: 
      self.fields[field].widget.attrs['readonly'] = 'true' 
+0

這是否意味着每當創建一個PersonForm表單對象時,它將不可編輯? – Mona

+1

是的,這意味着PersonForm的所有字段將是不可編輯的。如果您只想將某些字段設置爲不可編輯,則編輯代碼。 –

0

我知道,老問題,但因爲我有同樣的問題,這周可能會有所幫助其他人。 只有當您希望整個表單爲只讀時,此技巧纔有效。它會覆蓋任何發佈的數據(請參閱def clean(self)),並將小部件屬性設置爲只讀。

注意:將窗口小部件屬性設置爲只讀並不會阻止更改模型對象實例。

class MyModelForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     super(MyModelForm, self).__init__(*args, **kwargs) 

     if self.is_readonly(): 
      for k,f in self.fields.iteritems(): 
       f.widget.attrs['readonly'] = True 

    def clean(self): 
     if self.is_readonly(): 
       return {} 
     return super(CompanyQuestionUpdateForm, self).clean() 

    def is_readonly(self, question): 
     if your_condition: 
      return True 
     return False 

    class Meta: 
     model = MyModel 
0

,能夠實現場插件呈現包裹成格或TD結合的ModelForm字段值,樣品實現是有

https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/master/django_jinja_knockout/widgets.py

# Read-only widget for existing models. 
class DisplayText(Widget): 

然後形式元類可以被實現將自動將所有ModelForm字段的字段控件設置爲DisplayText:

https://github.com/Dmitri-Sintsov/djk-sample/search?utf8=%E2%9C%93&q=DisplayModelMetaclass

class ClubDisplayForm(BootstrapModelForm, metaclass=DisplayModelMetaclass): 

    class Meta(ClubForm.Meta): 
     widgets = { 
      'category': DisplayText() 
     } 

隨意使用或開發自己的widget/form元類版本。

有大約只讀ModelForms在Django的錯誤門票討論:

https://code.djangoproject.com/ticket/17031

封閉,「櫨是爲處理數據,而不是渲染它。」

但我認爲,這些原因的錯誤:

  • ModelForms不只是處理數據,他們還繪製表格模型。只讀映射是映射的子集。

  • 有內嵌窗體集和只讀內聯窗體集更加方便,它爲手動呈現關係留下了很多負擔。

  • 基於類的視圖可以共享公共模板以顯示和編輯ModelForms。因此只讀顯示的ModelForms增加了DRY(Django的一個關鍵原理)。

相關問題