天天看點

寫一個道地的django model

做web開發,編碼往往以模組化開始,下面以django1.5為标準,扯扯寫一個道地的django model.(django1.4絕大部分可以相容)

1.首先要對Field Options有個基本的認識(屬性是面向model類而言的,字段是面向資料庫而言的)

    model由屬性field組成,不同field類型,有不同的options,先了解所有field都公共的options。官網有比較多的options,選取正常開發能用到的幾個說一說。

    null選項, 表示資料庫層面的檢驗,能否為null,預設為False,就是說資料庫裡這個屬性對應的字段預設不能存儲null

    blank選項,能否為空值empty value(不是None空對象),None存到資料庫就是null,這個選項與資料庫無關,是一個純django層面的檢驗,比如form的校驗,能否允許empty value就取決于這個選項

    choices選項,指定這個屬性的值隻能是哪幾種可能,具體寫法看文檔https://docs.djangoproject.com/en/1.5/ref/models/fields/#django.db.models.Field.choices

    db_column選項,指定資料庫表裡這個屬性對應字段的名字,預設是屬性名字,無特殊需要,不用理會。如果實際需要更改,比如使用一個已經存在的資料庫,確定名字可用

    db_index選項,是否為這個屬性對應字段添加索引,即使有這個需要,unique可以勝任

    default,不用說了,賦預設值

    editable,是否可編輯,預設true,如果不可編輯,将不會再model-form和admin中的添加修改出現

    error_messages,該屬性使用者輸入不符合要求時,提示資訊,預設已有,除非不滿足你的要求,不用理會。

  help_text,幫助資訊,當使用者輸入填寫表單時,提示使用者這個該怎麼輸入

  verbose_name,官網有個解釋很好A human-readable name for the field。簡略的說:屬性名cat,verbose_name=U"貓",那麼頁面上就顯示貓,不是cat

2.寫好每一個屬性

  1.數值字元串類型:大整數使用 BigIntegerField

              一般IntegerField

              确定值很小 可以節約空間使用 SmallIntegerField

    浮點數,高精度浮點,字元串,布爾,IP,郵箱,URL,等等分别使用其對應類型即可,另外有些帶Positive修飾,檢驗正負,總之一句話:請使用最精确的類型。

    此外CommaSeparatedIntegerField不是整數,别被名字騙了,本質還是字元串

    大量文本使用TextField,個人覺得百K是上限,再大過M就不适合了

    更大,那就自定義類型,指向底層資料庫支援的大資料類型,這個比較簡單。

  2.日期時間類型:DateField,TimeField,DateTimeField

    如果你要記錄首次添加時間,auto_now_add=True

    如果你要記錄最後更新時間,auto_now=True,這兩個就不要自己動腦筋實作了

    但是注意QuerySet批量更新時,不是依次調用每個對象的更新函數,不會觸發auto_now,批量更新其他字段時記得連帶更新最後時間

 3.上傳檔案,使用FileField相關文檔太長,簡要概括

    upload_to指定上傳目錄,storage如何管理你上傳的檔案,預設就夠用。有幾個可選,看看差異即可。

    但是,models類讀取檔案屬性和普通屬性有所差別:

    讀取檔案屬性傳回值是一個FieldFile對象,代表你上傳的檔案,這個對象的url屬性表示檔案路徑,open,close,delete,save方法用于操作檔案。

    此外FilePathField與檔案基本無關,也别被名字騙了,本質是個字元串,隻不過要求這個字元串表示的檔案路徑正确有效,有些選項可以控制檔案或目錄,不詳述。

    ImageField是FileField子類,隻不過加了幾個與圖檔相關的控制參數,用法一樣

  4.外鍵,比如

    1.class Comment(models.Model):

         target = models.ForeignKey(XXX)#XXX另一個model 類,表示對XXX的一個評論

      如果外鍵要指向自己,比如要表示對評論的評論,使用self,或者自己的類名parent =models.ForeignKey('self')或者models.ForeignKey('Comment')

      parent就表示上一級評論,使用字元串表示類名,在程式運作時,這個類名必須能在ContentType找到,簡單點說,就是存在并且被django加載了。不了解django的ContentType沒關系,不需要用django内置的一些玩意就用不着。

   2.related_name,指定反向查找時的key,舉例:

      上例中xxx.comment_set.all()可以取出該XXX的所有評論,是因為預設related_name就是類名Comment的全小寫comment+"_set",預設就夠使用了

       什麼時候必須指定呢?上面的model添加兩個屬性

      from_user =models.ForeignKey(User, related_name='from_me')

      to_user =models.ForeignKey(User, related_name='to_me')

       此時如不指定related_name就會報錯,因為django不知道該如何反向取值了。如果按照上面分别指定了related_name,那麼外鍵反向取值,如下

      user.from_me.all()就能取出我發出的所有評論

      user.to_me.all()取出所有發給我的評論

    3.limit_choices_to 沒啥說的,限制外鍵取值範圍

    4.to_field,是指外鍵指向另一個表(模型)的哪一個字段(屬性),預設指向主鍵id.可以修改指向别的字段(屬性),不過確定其唯一性

     5.on_delete是說外鍵指向的對象删除時,本對象應該采取的措施,預設級聯删除。

        一共有cascade, protect, set_null, set_default, set(), do_nothing等選擇,詳見https://docs.djangoproject.com/en/1.5/ref/models/fields/#django.db.models.ForeignKey.on_delete

   5.多對多

      跟外鍵差不多,隻說不同的。

           1. symmetrical,對稱性。比如User有個多對多鍵friends指向User,我添加你做朋友,自動地,你也是我的朋友,這就是對稱性,預設為true,開啟。

            可以設定False,關閉後,我添加你做朋友,我的好友清單有你。你的好友清單沒有我。

          2.through,過渡表。django預設的多對多實作是采用中間過渡表完成。比如A多對多B,那麼有張中間表

                 id:中間表自己的主鍵

                a_id:指向A表主鍵

                b_id指向B表主鍵

            用這張過渡表記錄AB的多對多關系。很遺憾,這張表就隻有三個字段,不能記錄其他資訊,比如我是什麼時間添加你做朋友。想要存儲額外資訊到過渡表,就該 使用through了。官網有個例子https://docs.djangoproject.com/en/1.5/topics/db/models/#intermediary-manytomany

           3.db_table,過渡表表名。如上文,AB多對多過渡表表名預設為a_b,二者類名下劃線連結,再小寫。你可以指定其他名字。

     6.一對一,跟外鍵幾乎一樣,多一個選項(options),叫parent_link,沒啥大作用。給個位址看看官網解釋https://docs.djangoproject.com/en/1.5/ref/models/fields/#django.db.models.OneToOneField.parent_link

3.最後一點了,Meta設定

       abstract 用來指定是否是抽象類,抽象類不會生成表,适合用于面向對象的基類

    app_label預設不用指定,django自省即可(别問什麼是自省啊,有百度可以問)。當你的model定義在models.py或者models包外時,或者是動态模型,那就必須指定了,值就是你的app名字即可。關于動态模型,詳見django dynamic models and field injections

    db_table預設值是“appName”+“_”+ “modelName”,可以指定别的表名。使用已存在的庫表時有用。

    get_latest_by,指定django的latest函數取最新記錄時預設按什麼排序

    ordering指定模型預設按什麼排序,注意此設定會反映到資料庫層面,并且會有外鍵傳遞影響

    permissions指定該模型需要額外建立的權限代碼,預設add  change  delete 三種

       unique_together  指定資料庫表中哪幾列必須組合起來唯一,不能全部相同。同聯合主鍵。

        index_together  指定資料庫表中哪幾列必須組合起來建立索引。與unique_together唯一差別在于不要求組合唯一。

       verbose_name給你的模型取一個好了解的好閱讀的名字在頁面上顯示,

verbose_name_plural是verbose_name的複數,預設verbose_name+“s“
      
proxy order_with_respect_to不常用,managed一般不需改變,有需要可看看文檔      

充分利用django内置的實作完成你的功能,不要自己苦思冥想去實作一些偏僻的功能,而且盡最大可能寫最精确的代碼,就OK了。