来一个简单的例子吧。
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()
|