Django 模型中自定義字段類型Field

來一個簡單的例子吧。

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()
以上內容是來自Django自強學堂
發佈了16 篇原創文章 · 獲贊 13 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章