Django入门-5:模型的基本使用2-字段

简介: Django入门-5:模型的基本使用2-字段

定义属性

  1. 定义属性时,需要字段类型
  2. 字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models
  3. 使用方式
  4. 导入from django.db import models
  5. 通过models.Field创建字段类型的对象,赋值给属性
  6. 对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False


字段类型

  1. AutoField:一个根据实际ID自动增长的IntegerField,通常不指定
  2. 如果不指定,一个主键字段将自动添加到模型中
  3. BooleanFieldtrue/false 字段,此字段的默认表单控制是CheckboxInput
  4. NullBooleanField:支持nulltruefalse三种值
  5. CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
  6. TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
  7. IntegerField:整数
  8. DecimalField(max_digits=None, decimal_places=None):使用pythonDecimal实例表示的十进制浮点数
  9. DecimalField.max_digits:位数总数
  10. DecimalField.decimal_places:小数点后的数字位数
  11. FloatField:用Pythonfloat实例来表示的浮点数
  12. TimeField:使用Python的datetime.time实例表示的时间,参数同DateField
  13. DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
  14. FileField:一个上传文件的字段
  15. ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
  16. DateField[auto_now=False, auto_now_add=False]):使用Pythondatetime.date实例表示的日期
  • 参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,
  • 它总是使用当前日期,默认为false
  •  
  • 参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,
  • 它总是使用当前日期,默认为false
  •  
  • 该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,
  • 包含了一个额外的invalid_date错误消息键
  •  
  • auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果


字段选项

  • 通过字段选项,可以实现对字段的约束
  • 在字段对象时通过关键字参数指定
  1. db_column:字段的名称,如果未指定,则使用属性的名称
  2. db_index:若值为 True, 则在表中会为此字段创建索引
  3. default:默认值
  4. primary_key:若为 True, 则该字段会成为模型的主键字段
  5. unique如果为 True, 这个字段在表中必须有唯一值
  6. max_length:字段最大的长度
  7. null:如果为TrueDjango 将空值以NULL 存储到数据库中,默认值是 False
  8. blank:如果为True,则该字段允许为空白,默认值是 False

对比null是数据库范畴的概念,blank是表单验证证范畴的

 

关系

关系的类型包括

ForeignKey:一对多,将字段定义在多的端中

ManyToManyField:多对多,将字段定义在两端中

OneToOneField:一对一,将字段定义在任意一端中

可以维护递归的关联关系,使用'self'指定,详见“自关联”

#示例

from django.db import models
# Create your models here.
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateTimeField()
def __str__(self):
return "%d" % self.pk
class HeroInfo(models.Model):
hname = models.CharField(max_length=20)
hgender = models.BooleanField()
hcontent = models.CharField(max_length=100)
hBook = models.ForeignKey('BookInfo')
def __str__(self):
return "%d" % self.pk
  • 用一访问多:对象.模型类小写_set

bookinfo.heroinfo_set

  • 用一访问一:对象.模型类小写

heroinfo.bookinfo

  • 访问id:对象.属性_id

heroinfo.book_id


元选项

  • 在模型类中定义类Meta,用于设置元信息
  • 元信息db_table:定义数据表名称,推荐使用小写字母,数据表的默认名称

<app_name>_<model_name>

  • ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表

class BookInfo(models.Model):

...

class Meta():

ordering = ['id']

  • 字符串前加-表示倒序,不加-表示正序

class BookInfo(models.Model):

...

class Meta():

ordering = ['-id']

  • 排序会增加数据库的开销


示例演示

创建test2项目,并创建booktest应用,使用mysql数据库

  • 定义图书模型
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateTimeField()
bread = models.IntegerField(default=0)
bcommet = models.IntegerField(default=0)
isDelete = models.BooleanField(default=False)
  • 英雄模型
class HeroInfo(models.Model):
hname = models.CharField(max_length=20)
hgender = models.BooleanField(default=True)
isDelete = models.BooleanField(default=False)
hcontent = models.CharField(max_length=100)
hbook = models.ForeignKey('BookInfo')


  • 定义index、detail视图
# Create your views here.
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.template import loader
from django.urls import reverse
from booktest.models import BookInfo
def index(request):
# return HttpResponse("欢迎来到 Django首页!")
booklist = BookInfo.objects.all()
template = loader.get_template('booktest/index.html')
# context = RequestContext(request, {'booklist': booklist})
context = {'booklist': booklist}
return HttpResponse(template.render(context))
def detail(request, id):
# return HttpResponse("DETAIL %s" % id)
book = BookInfo.objects.get(pk=id)
template = loader.get_template('booktest/detail.html')
# context = RequestContext(request, {'book': book})
context = {'book': book}
return HttpResponse(template.render(context))
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a) + int(b)
return HttpResponse(str(c))
def add2(request, a, b):
c = int(a) + int(b)
return HttpResponse(str(c))
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse # django 1.4.x - django 1.10.x
# from django.urls import reverse # new in django 1.10.x
def old_detail(request, a, ):
return HttpResponseRedirect(
reverse('detail', args=(a))
)
  • index.html、detail.html模板
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>图书列表</h1>
<ul>
{% for book in booklist %}
<li>
{# {% comment %}<a href="{{ book.id }}">{% endcomment %}#}
<a href="{% url 'detail' book.id %}">
{{ book.btitle }}
</a>
</li>
{% endfor %}
</ul>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>详细页</title>
</head>
<body>
<h1>{{ book.btitle }}</h1>
<ul>
{% for hero in book.heroinfo_set.all %}
<li>{{ hero.hname }}---{{ hero.hcontent }}</li>
{% endfor %}
</ul>
</body>
</html>
  • 配置url,能够完成图书及英雄的展示
from django.conf.urls import url, include
from django.contrib import admin
from booktest import views
urlpatterns = [
url(r'^add/$', views.add, name='add'),
url(r'^add/(\d+)/(\d+)/$', views.add2, name='add2'),
url(r'^$', views.index),
url(r'^([0-9]+)/$', views.old_detail),
url(r'^book/([0-9]+)/$', views.detail, name="detail"),
url(r'^admin/', admin.site.urls),
]

测试数据

  • 模型BookInfo的测试数据
insert into booktest_bookinfo(btitle,bpub_date,bread,bcommet,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0)
  • 模型HeroInfo的测试数据
insert into booktest_heroinfo(hname,hgender,hbook_id,hcontent,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0)


自定义Field

Django 的官方提供了很多的 Field,但是有时候还是不能满足我们的需求,不过Django提供了自定义 Field 的方法:

来一个简单的例子吧。

1. 减少文本的长度,保存数据的时候压缩,读取的时候解压缩,如果发现压缩后更长,就用原文本直接存储:

Django 1.7 以下

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 以上版本,可以用


#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,代码如下:

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 一样使用:

class Article(models.Model):
labels = ListField()

在终端上尝试(运行 python manage.py shell 进入):

  1. >>> from app.models import Article
  2. >>> d = Article()
  3. >>> d.labels
  4. []
  5. >>> d.labels = ["Python", "Django"]
  6. >>> d.labels
  7. ["Python", "Django"]
  8. >>> from blog.models import Article
  9.  
  10. >>> a = Article()
  11. >>> a.labels.append('Django')
  12. >>> a.labels.append('custom fields')
  13.  
  14. >>> a.labels
  15. ['Django', 'custom fields']
  16.  
  17. >>> type(a.labels)
  18. <type 'list'>
  19.  
  20. >>> a.content = u'我正在写一篇关于自定义Django Fields的教程'
  21. >>> a.save()

参考来源:http://code.ziqiangxuetang.com/django/django-custom-field.html


目录
相关文章
|
1月前
|
Java API 数据库
Django:从入门到精通
【11月更文挑战第18天】Django是一个由Python编写的高级Web应用框架,以其简洁性、安全性和高效性而闻名。Django最初由Adrian Holovaty和Simon Willison于2003年开发,旨在简化Web应用的开发过程。作为一个开放源代码项目,Django迅速吸引了大量的开发者和用户,成为了Python Web开发领域的重要工具之一。
45 1
|
2月前
|
数据库 Python
django中的models.ManyToManyField 字段如何新增,通过Category,如何反向查询Product
django中的models.ManyToManyField 字段如何新增,通过Category,如何反向查询Product
69 10
|
2月前
|
机器学习/深度学习 前端开发 网络架构
Django如何调用机器学习模型进行预测
Django如何调用机器学习模型进行预测
75 5
|
2月前
|
机器学习/深度学习 监控 数据挖掘
基于Django和百度飞桨模型的情感识别Web系统
基于Django和百度飞桨模型的情感识别Web系统
45 5
|
2月前
|
机器学习/深度学习 算法 搜索推荐
django调用矩阵分解推荐算法模型做推荐系统
django调用矩阵分解推荐算法模型做推荐系统
43 4
|
2月前
|
存储 Shell 数据库
Python编程--Django入门:用户账户(二)
Python编程--Django入门:用户账户(二)
28 2
|
2月前
|
存储 数据库 Python
Python编程--Django入门:用户账户(一)
Python编程--Django入门:用户账户(一)
20 1
|
2月前
|
存储 开发框架 JSON
【查漏补缺】Django模型字段类型及其应用
【查漏补缺】Django模型字段类型及其应用
29 0
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
171 45
|
1月前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
59 2