定义属性

  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. BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput
  4. NullBooleanField:支持null、true、false三种值
  5. CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
  6. TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
  7. IntegerField:整数
  8. DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数
  9. DecimalField.max_digits:位数总数
  10. DecimalField.decimal_places:小数点后的数字位数
  11. FloatField:用Python的float实例来表示的浮点数
  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]):使用Python的datetime.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:如果为True,Django 将空值以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.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 进入):

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

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

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

  1. 【Django入门】——模型管理器对象、模型管理器类和模型类

    文章目录 一.模型管理器对象 1. 自定义模型管理器对象 2. 自定义模型管理器类 3. 自定义模型管理器类应用 3.1 重写框架的方法 3.2 封装自定义方法 4. 模型管理器对象的`model`属 ...

  2. Django 入门项目案例开发(上)

    关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. Django 入门案例开发(中) http://www.cnblogs.com/focusBI ...

  3. Django入门(二) 理解Django生命流程周期

    接上篇:Django入门-项目创建与初识子应用 项目的数据库模型 这里我们先使用sqlite类型的数据库,后面在进行改变 创建数据库模型 名词: ORM(Object Ralational Mappi ...

  4. 超实用的Django入门基础教程,新手必备!

    Django入门基础教程 Django简介 安装Django 虚拟环境的建立和准备工作 一.通过pycharm创建 手动创建app 迁移数据库 二.手动创建 创建一个新的文件夹 创建虚拟环境 激活虚拟 ...

  5. Django入门 | 官方文档带你快速入门

    初识 Django 设计模型 应用数据模型 享用便捷的 API 一个动态管理接口:并非徒有其表 规划 URLs 编写视图 设计模板 这仅是基本入门知识 快速安装指南 安装 Python 设置数据库 安 ...

  6. 第一章:Django入门篇

    文章目录 第一章:Django入门篇 一. web应用 二.HTTP协议(重要) 请求协议 响应协议 响应状态码 URL简介 三.django简介 3.2 目录介绍 3.3 启动项目 3.4 简单示例 ...

  7. python编程从入门到实践 第18章Django入门 2022年最新

    说明:这篇文章只是记录自己自学本书的一个痕迹,日后来看作为一个念想.至于做为公开,是希望对一些同样跟我一样的朋友有一点点帮助,当然我本人就是小白,帮助可能也不大哈哈. 这篇文章记录了<pytho ...

  8. (译)一个完整的Django入门指南---第7部分

    1.前言 本篇文章是翻译 A Complete Beginner's Guide to Django 系列的最后一篇文章 A Complete Beginner's Guide to Django - ...

  9. Django入门项目

    刘江的博客 个人博客和教程网站:www.liujiangblog.com欢迎访问! </div><!--end: blogTitle 博客的标题和副标题 --> <div ...

最新文章

  1. 关于mybatis中基本类型条件判断问题
  2. 推荐算法三视角:矩阵,图,时间线
  3. 西里尔字符_如何设计西里尔字母Њ(Nje),Љ(Lje),Ћ(Tshe)和Ђ(Dje)
  4. java如何运行一个任务_如何每天从Java运行任务?
  5. leetcode603. 连续空余座位(SQL)
  6. java中 怎么获取bean_java普通类如何得到spring中的bean类
  7. 【记录】Docker push 到dockerhub网站
  8. 小汤学编程之JavaScript学习day04——自定义对象、原型与原型链、BOM
  9. [圣诞记]HULK七周年庆
  10. php如何请求api,PHP如何发送GET/POST请求调用API
  11. [机器学习1]线性回归
  12. Django之Form插件
  13. 对话张悦然:当年新概念作文大赛获奖者 现在怎样了
  14. 开启 TLS 1.3 加密协议,极速 HTTPS 体验
  15. 20200125每日一句
  16. Matlab R2010b 安装使用教程 【详细】
  17. 最大公约数的四种求法(暴力、短除法、辗转相除法递归和非递归)
  18. 牛客寒假算法基础训练营3 G.糖果
  19. 开发操作系统(2)键盘驱动
  20. 万众瞩目的BAISS公链将如何彻底改变区块链现状?

热门文章

  1. VBA 学习笔记 Wrod表格设置
  2. H5的Audio API音频
  3. 程序员与公务员妳选择哪个
  4. 常见的量化交易策略简介
  5. 搭建单机测试SequoiaDB
  6. leetcode/狒狒吃香蕉
  7. Flex 布局教程——阮老师
  8. linux mrtg 安装,Linux系统mrtg详细安装、设置说明
  9. Selenium-Switch与SelectApi接口详解
  10. WIN7激活显示 系统保留分区未分配驱动器号,怎么分配?求解!!!!!