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


目录
相关文章
|
25天前
|
关系型数据库 MySQL 数据库
数据迁移脚本优化过程:从 MySQL 到 Django 模型表
在大规模的数据迁移过程中,性能问题往往是开发者面临的主要挑战之一。本文将分析一个数据迁移脚本的优化过程,展示如何从 MySQL 数据库迁移数据到 Django 模型表,并探讨优化前后的性能差异。
|
26天前
|
JSON API 数据格式
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
|
24天前
|
关系型数据库 MySQL 数据库
『Django』模型入门教程-操作MySQL
一个后台如果没有数据库可以说废了一半。日常开发中大多数时候都在与数据库打交道。Django 为我们提供了一种更简单的操作数据库的方式。 在 Django 中,模型(Model)是用来定义数据库结构的类。每个模型类通常对应数据库中的一个表,类的属性对应表中的列。通过定义模型,Django 的 ORM(Object-Relational Mapping)可以将 Python 对象映射到数据库表,并提供一套 API 来进行数据库操作。 本文介绍模型的用法。
|
26天前
|
存储 SQL 数据处理
Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
|
26天前
|
数据库 开发者 Python
Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作
Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作
|
8月前
|
SQL 关系型数据库 MySQL
07 Django模型 - ORM简介及MySQL数据库的使用
07 Django模型 - ORM简介及MySQL数据库的使用
47 0
|
数据库 Python 关系型数据库
Django模型简介
模型是一个定义数据源的数据,它包含要存储数据的一些属性和行为。通常,每一个模型对应数据库中的一个数据表。 每一个模型是django.db.models.Model的子类 每一个模型属性代表数据表的一个字段。
963 0
|
1月前
|
Linux 数据库管理 Python
CentOS7编译安装Python3.10(含OpenSSL1.1.1安装),创建虚拟环境,运行Django项目(含sqlite版本报错)
CentOS7编译安装Python3.10(含OpenSSL1.1.1安装),创建虚拟环境,运行Django项目(含sqlite版本报错)
211 4
|
1月前
|
开发框架 数据库 开发者
Web开发新境界:用Python玩转Django和Flask!
【6月更文挑战第12天】Python的Web开发框架Django和Flask各有千秋。Django是全能型框架,适合快速开发大型应用,提供ORM、模板引擎、URL路由和后台管理等全面功能。Flask则轻量级且灵活,适用于小型到中型应用,以其简单易用、高度可扩展和灵活路由著称。两者结合使用,能应对各种Web开发需求。
|
1月前
|
前端开发 JavaScript 数据安全/隐私保护
计算机Python项目|django学生成绩管理系统
计算机Python项目|django学生成绩管理系统