來一個簡單的例子吧。
1. 減少文本的長度,保存數據的時候壓縮,讀取的時候解壓縮,如果發現壓縮後更長,就用原文本直接存儲:
Django 1.7 以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | from django.db import models class CompressedTextField(models.TextField): """ model Fields for storing text in a compressed format (bz2 by default) """ __metaclass__ = models.SubfieldBase def to_python( self , value): if not value: return value try : return value.decode( 'base64' ).decode( 'bz2' ).decode( 'utf-8' ) except Exception: return value def get_prep_value( self , value): if not value: return value try : value.decode( 'base64' ) return value except Exception: try : tmp = value.encode( 'utf-8' ).encode( 'bz2' ).encode( 'base64' ) except Exception: return value else : if len (tmp) > len (value): return value return tmp |
to_python 函數用於轉化數據庫中的字符到 Python的變量, get_prep_value 用於將Python變量處理後(此處爲壓縮)保存到數據庫,使用和Django自帶的 Field 一樣。
Django 1.8 以上版本,可以用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #coding:utf-8 from django.db import models class CompressedTextField(models.TextField): """ model Fields for storing text in a compressed format (bz2 by default) """ def from_db_value( self , value, expression, connection, context): if not value: return value try : return value.decode( 'base64' ).decode( 'bz2' ).decode( 'utf-8' ) except Exception: return value def to_python( self , value): if not value: return value try : return value.decode( 'base64' ).decode( 'bz2' ).decode( 'utf-8' ) except Exception: return value def get_prep_value( self , value): if not value: return value try : value.decode( 'base64' ) return value except Exception: try : return value.encode( 'utf-8' ).encode( 'bz2' ).encode( 'base64' ) except Exception: return value |
Django 1.8及以上版本中,from_db_value 函數用於轉化數據庫中的字符到 Python的變量。
2. 比如我們想保存一個 列表到數據庫中,在讀取用的時候要是 Python的列表的形式,我們來自己寫一個 ListField:
這個ListField繼承自 TextField,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from django.db import models import ast class ListField(models.TextField): __metaclass__ = models.SubfieldBase description = "Stores a python list" def __init__( self , * args, * * kwargs): super (ListField, self ).__init__( * args, * * kwargs) def to_python( self , value): if not value: value = [] if isinstance (value, list ): return value return ast.literal_eval(value) def get_prep_value( self , value): if value is None : return value return unicode (value) # use str(value) in Python 3 def value_to_string( self , obj): value = self ._get_val_from_obj(obj) return self .get_db_prep_value(value) |
使用它很簡單,首先導入 ListField,像自帶的 Field 一樣使用:
1 2 | class Article(models.Model): labels = ListField() |
在終端上嘗試(運行 python manage.py shell 進入):
1 2 3 4 5 6 7 | >>> from app.models import Article >>> d = Article() >>> d.labels [] >>> d.labels = [ "Python" , "Django" ] >>> d.labels [ "Python" , "Django" ] |
下載上面的代碼,解壓,進入項目目錄,輸入 python manage.py shell 搞起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> from blog.models import Article >>> a = Article() >>> a.labels.append( 'Django' ) >>> a.labels.append( 'custom fields' ) >>> a.labels [ 'Django' , 'custom fields' ] >>> type (a.labels) < type 'list' > >>> a.content = u '我正在寫一篇關於自定義Django Fields的教程' >>> a.save() |