Django入门-5:模型的基本使用2-字段
定义属性
定义属性时,需要字段类型
字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中
使用方式
导入from django.db import models
通过models.Field创建字段类型的对象,赋值给属性
对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
字段类型
AutoField:一个根据实际ID自动增长的IntegerField,通常不指定
如果不指定,一个主键字段将自动添加到模型中
BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput
NullBooleanField:支持null、true、false三种值
CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
IntegerField:整数
DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数
DecimalField.max_digits:位数总数
DecimalField.decimal_places:小数点后的数字位数
FloatField:用Python的float实例来表示的浮点数
TimeField:使用Python的datetime.time实例表示的时间,参数同DateField
DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
FileField:一个上传文件的字段
ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示的日期
参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,
它总是使用当前日期,默认为false
参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,
它总是使用当前日期,默认为false
该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,
包含了一个额外的invalid_date错误消息键
auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
字段选项
通过字段选项,可以实现对字段的约束
在字段对象时通过关键字参数指定
db_column:字段的名称,如果未指定,则使用属性的名称
db_index:若值为 True, 则在表中会为此字段创建索引
default:默认值
primary_key:若为 True, 则该字段会成为模型的主键字段
unique:如果为 True, 这个字段在表中必须有唯一值
max_length:字段最大的长度
null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
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.pkclass 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 HttpResponsefrom django.http import HttpResponseRedirectfrom django.template import loaderfrom django.urls import reversefrom booktest.models import BookInfodef 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 HttpResponseRedirectfrom django.core.urlresolvers import reverse # django 1.4.x - django 1.10.x# from django.urls import reverse # new in django 1.10.xdef 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, includefrom django.contrib import adminfrom booktest import viewsurlpatterns = [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 modelsclass CompressedTextField(models.TextField):""" model Fields for storing text in a compressed format (bz2 by default) """__metaclass__ = models.SubfieldBasedef to_python(self, value):if not value:return valuetry:return value.decode('base64').decode('bz2').decode('utf-8')except Exception:return valuedef get_prep_value(self, value):if not value:return valuetry:value.decode('base64')return valueexcept Exception:try:tmp = value.encode('utf-8').encode('bz2').encode('base64')except Exception:return valueelse:if len(tmp) > len(value):return valuereturn tmp
- to_python 函数用于转化数据库中的字符到 Python的变量,
- get_prep_value 用于将Python变量处理后(此处为压缩)保存到数据库,
- 使用和Django自带的 Field 一样。
Django 1.8 以上版本,可以用
#coding:utf-8from django.db import modelsclass 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 valuetry:return value.decode('base64').decode('bz2').decode('utf-8')except Exception:return valuedef to_python(self, value):if not value:return valuetry:return value.decode('base64').decode('bz2').decode('utf-8')except Exception:return valuedef get_prep_value(self, value):if not value:return valuetry:value.decode('base64')return valueexcept 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 modelsimport astclass ListField(models.TextField):__metaclass__ = models.SubfieldBasedescription = "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 valuereturn ast.literal_eval(value)def get_prep_value(self, value):if value is None:return valuereturn unicode(value) # use str(value) in Python 3def 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 进入):
>>> from app.models import Article
>>> d = Article()
>>> d.labels
[]
>>> d.labels = ["Python", "Django"]
>>> d.labels
["Python", "Django"]
>>> 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()
参考来源:http://code.ziqiangxuetang.com/django/django-custom-field.html
Django入门-5:模型的基本使用2-字段相关推荐
- 【Django入门】——模型管理器对象、模型管理器类和模型类
文章目录 一.模型管理器对象 1. 自定义模型管理器对象 2. 自定义模型管理器类 3. 自定义模型管理器类应用 3.1 重写框架的方法 3.2 封装自定义方法 4. 模型管理器对象的`model`属 ...
- Django 入门项目案例开发(上)
关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. Django 入门案例开发(中) http://www.cnblogs.com/focusBI ...
- Django入门(二) 理解Django生命流程周期
接上篇:Django入门-项目创建与初识子应用 项目的数据库模型 这里我们先使用sqlite类型的数据库,后面在进行改变 创建数据库模型 名词: ORM(Object Ralational Mappi ...
- 超实用的Django入门基础教程,新手必备!
Django入门基础教程 Django简介 安装Django 虚拟环境的建立和准备工作 一.通过pycharm创建 手动创建app 迁移数据库 二.手动创建 创建一个新的文件夹 创建虚拟环境 激活虚拟 ...
- Django入门 | 官方文档带你快速入门
初识 Django 设计模型 应用数据模型 享用便捷的 API 一个动态管理接口:并非徒有其表 规划 URLs 编写视图 设计模板 这仅是基本入门知识 快速安装指南 安装 Python 设置数据库 安 ...
- 第一章:Django入门篇
文章目录 第一章:Django入门篇 一. web应用 二.HTTP协议(重要) 请求协议 响应协议 响应状态码 URL简介 三.django简介 3.2 目录介绍 3.3 启动项目 3.4 简单示例 ...
- python编程从入门到实践 第18章Django入门 2022年最新
说明:这篇文章只是记录自己自学本书的一个痕迹,日后来看作为一个念想.至于做为公开,是希望对一些同样跟我一样的朋友有一点点帮助,当然我本人就是小白,帮助可能也不大哈哈. 这篇文章记录了<pytho ...
- (译)一个完整的Django入门指南---第7部分
1.前言 本篇文章是翻译 A Complete Beginner's Guide to Django 系列的最后一篇文章 A Complete Beginner's Guide to Django - ...
- Django入门项目
刘江的博客 个人博客和教程网站:www.liujiangblog.com欢迎访问! </div><!--end: blogTitle 博客的标题和副标题 --> <div ...
最新文章
- 关于mybatis中基本类型条件判断问题
- 推荐算法三视角:矩阵,图,时间线
- 西里尔字符_如何设计西里尔字母Њ(Nje),Љ(Lje),Ћ(Tshe)和Ђ(Dje)
- java如何运行一个任务_如何每天从Java运行任务?
- leetcode603. 连续空余座位(SQL)
- java中 怎么获取bean_java普通类如何得到spring中的bean类
- 【记录】Docker push 到dockerhub网站
- 小汤学编程之JavaScript学习day04——自定义对象、原型与原型链、BOM
- [圣诞记]HULK七周年庆
- php如何请求api,PHP如何发送GET/POST请求调用API
- [机器学习1]线性回归
- Django之Form插件
- 对话张悦然:当年新概念作文大赛获奖者 现在怎样了
- 开启 TLS 1.3 加密协议,极速 HTTPS 体验
- 20200125每日一句
- Matlab R2010b 安装使用教程 【详细】
- 最大公约数的四种求法(暴力、短除法、辗转相除法递归和非递归)
- 牛客寒假算法基础训练营3 G.糖果
- 开发操作系统(2)键盘驱动
- 万众瞩目的BAISS公链将如何彻底改变区块链现状?