Django数据模型(models)

序言

  由于先天具备Python简单而强大的数据库查询执行方法,Django非常适合开发数据库驱动网站。Django模型即Django数据库层。
Django 遵循MVC模式(Model-View-Controller):
  • M , 数据存取部分,由Django数据库层处理
  • V  , 选择显示哪些数据,由视图和模板处理
  • C  , 根据用户输入委派视图的部分,由URLconf设置,对于给定URL调用适当的Python函数
  由于 C 由框架自行处理,而Django更加关注的是模型(Model),模板(Template)和视图(Views),Django也被称为MTV架构。
在MTV开发模式中:
  • M, 代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如果存取,如何验证有效性,包含哪些行为以及数据之间的关系等。
  • T , 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
  • V , 代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。可以看做是模型和模板之间的桥梁。

1. 基本命令

# 数据库相关命令
python manage.py validate         # 验证模型的有效性,validate 命令检查你的模型语法和逻辑是否正确,如果一切正常,你会看到0 errors found. 
python manage.py sqlall app名称    # 输出models中数据库建库语句(以sql的方式输出)
python manage.py syncdb           # 同步你的模型到数据库的一个简单方法,他会通过INSTALLED_APPS里设置的app来检查数据库,如果表不存在则创建,需要注意的是,sync并不能将模型的修改或删除同步到数据库,如果你修改或删除一个模型,用syncdb提交,不会做任何处理。
python manage.py makemigrations   # Django 1.7.1以上版本使用,代替syncdb,生成一个数据库结构migrations里面的一个表
python manage.py migrate          # 根据migrations里面的表创建数据库
python manage.py flush            # 清除数据库
python manage.py dumpdata appname > appname.json  # 导出数据库
python manage.py loaddata appname.json            # 导入数据库
python manage.py dbshell          # 进入数据库

  

2.类的结构

      (1)基础类型

from django.db import models
class userinfo(models.Model):  # 这个类是用来生成数据库表的,必须继承models.Model
    name = models.CharField(max_length=30)
    email = models.EmailField()
    memo = models.TextField()

  (2)连表类型

一对多:models.ForeignKey("其他表")
多对多:models.ManyToManyField("其他表")
一对一:models.OneToOneField("其他表")

  

应用场景:

	* 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被视为重复选择) # 示例:创建用户时,选择用户类型
	* 多对多:在某表中创建一行数据时,有一个可以多选的下拉框                  # 示例:创建用户时,用户指定的多个爱好
	* 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失)   # 示例:表里有10列数据,一段时间后需要添加5列

  (3)字段类型

常用字段说明:

    * AutoField :自增列,如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
    * BigAutoField :bigint 自增列,64位整数,1到9223372036854775807。必须参数:primary_key=True
    * SmallIntegerField :小整数,范围 -32768~35767
    * PositiveSmallIntegerField :正整数,范围:0~32767
    * PositiveIntegerField :正整数,范围:0~2147483647
    * IntegerField :整数列(有符号),范围:-2147483648~2147483647
    * BigIntegerFiled :长整型(有符号的)-9223372036854775808~9223372036854775807
    * BooleanField :布尔值,不能为空,如果没有定义默认值,则默认为None
    * NullBooleanField :可以为空的布尔值
    * CharFiled : 字符串类型,必须提供max_length参数,表示字符长度
    * TextField :文本类型,大文本字段
    * EmailField :本质上依然是字符串类型,在django admin和ModelForm中提供邮箱格式验证
    * IPAddressField :字符串类型,提供IPV4验证,高版本中可能会报错,被下面的替代
    * GenericIPAddressFiled :字符串类型,提供ipv4和ipv6两种验证

        * GenericIPAddressField(protocol='both', unpack_ipv4=False,**opthions)
        * 参数:protocol,用于指定ipv4和ipv6,默认是both表示两者都选,匹配不区分大小写
        * 参数:unpack_ipv4,压缩ipv4映射地址::ffff:192.0.2.1将被压缩为192.0.2.1。默认为禁用,只能在protocol设置时使用'both'
    * URLField :字符串类型,django提供URL验证
    * SlugField :字符串类型,django提供验证,支持字母,数字,下划线,连接符
    * ComaSeparatedIntegerField :字符串类型,格式必须是逗号分隔的数字. 继承了CharField,所以必须有max_length参数
    * UUIDField :字符串类型,django提供对UUID格式的验证

        * id = modles.UUIDField(primary_key=True,default=uuid.uuid4, editable=False)
    * FilePathField :字符串类型,django提供读取文件夹下文件的功能

        * FilePathField(path=None,match=None,recursive=False,max_length=100, **options)
        * 示例:models.FilePathField(path="/home/file", match="foo.*", recursive=True)
        * path:文件夹路径
        * match:正则匹配
        * recursive:递归下面的文件夹
        * allow_files=True:允许文件
        * allow_folers=False:允许文件夹
    * FileField :字符串,路径保存在数据库,文件上传到指定目录,两个可选参数

        * upload_to = ""  上传文件的保存路径

            * upload = models.FileField(upload_to='uploads/')   # 第一种是上传到指定目录
            * upload = models.FileField(upload_to='uploads/%Y/%m/%d/')  # 第二种是上传到一个目录下的当前时间日期目录(uploads/2017/05/04)这种,方便管理。
        * storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
    * ImageField :字符串,路径保存在数据库,文件上传到指定目录

        * upload_to = ""  上传保存路径
        * storage = None  存储组件
        * width_field=None ,上传图片的宽度(字符串)
        * height_field=None, 上传图片的高度(字符串)
    * DateTimeField :日期+时间格式 YYYY-MM-DD HH:MM [:ss[.uuuuu]][TZ]

        * auto_now = True, 更新时间,每次更新都会自动更新
        * auto_now_add = True , 创建时间,不会更新
    * DateField :日期格式, YYYY-MM-DD

        * auto_now = True, 更新时间,每次更新都会自动更新
        * auto_now_add = True , 创建时间,不会更新
    * TimeField :时间格式,HH:MM [:ss[.uuuuu]]
    * DurationField :长整型,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta
    * FloatField :浮点型
    * DecimalField :10进制小数

        * max_digits : 小数总长度
        * decimal_places :小数位长度
    * BinaryField :二进制类型,它支持bytes.这个字段功能有限,不能在此字段值上做过滤查询,也不能用于ModelForm。
字段类型

 

  (4)参数类型

1、null=True  数据库中字段是否可以为空
2、blank=True  django的 Admin 中添加数据时是否可允许空值
3、primary_key = True  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add  
    auto_now 自动创建---无论添加或修改,都是当前操作的时间  
    auto_now_add 自动创建---永远是创建时的时间
5、choices
    GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), )
    gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length 最大长度
7、default  默认值
8、verbose_name  Admin中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to 上传到哪个位置,更多与image,filepath配合使用

  

表操作

  (1)基本操作

# 增
(1)第一种
models.Tb1.objects.create(c1='xx', c2='oo') # 向Tb1表增加一条数据,可以接受字典类型数据 **kwargs
(2)第二种
obj = models.Tb1(c1='xx', c2='oo')
obj.save()

# 查
models.Tb1.objects.get(id=123)  # 获取Tb1表中id=123的数据,不存在则报错(不建议使用)
models.Tb1.objects.all()        # 获取Tb1表的全部数据
models.Tb1.objects.filter(name='alex')  # 获取指定条件的数据

# 删
models.Tb1.objects.filter(name='alex').delete()  # 删除指定条件的数据

# 改
models.Tb1.objects.filter(name='alex').update(gender='0')   # 将指定条件的数据更新,均支持 **kwargs
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
obj.save()          # 修改单条数据

  (2)进阶操作(了不起的双下划线)

# 获取个数
models.Tb1.objects.filter(name='alex').count()

# 大于,小于
models.Tb1.objects.filter(id__gt=1)   # 获取id大于1的值
models.Tb1.objects.filter(id__lt=0    # 获取id小于10的值
models.Tb1.objects.filter(id__lt=10,id__gt=1)  # 获取id大于1且小于10 的值

# in
models.Tb1.objects.filter(id__in=[11,22,33])  # 获取id 等于11,22,33的数据
models.Tb1.objects.exclude(id_in=[11,22,33])  # not in

# contains
models.Tb1.objects.filter(name__contains="ven") # 获取name包含ven的数据
models.Tb1.objects.filter(name__icontains="ven")  # icontains不区分大小写
models.Tb1.objects.exclude(name__icontains="ven") # 获取name字段不包含ven的数据

# range
models.Tb1.objects.filter(id__range=[1,2])  # 范围bettwen and

# 其他类似
startswith  # 字段以什么开头
istartswith # 字段非以什么开头
endswith    # 字段以什么结尾
iendswith   # 字段非以什么结尾

# order by
models.Tb1.objects.filter(name="alex").order_by('id')  # asc  升序
models.Tb1.objects.filter(name="alex").order_by('-id') # desc 降序

# limit, offset
models.Tb1.objects.all()[10:20] # 获取Tb1表中第10条到第20条数据

# group by
from django.db.models import Conut, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

  

# F 使用查询条件的值
from django.db.models import F
models.Tb1.objects.update(num=F('num')+1)  # F('num') 获取数据库中当前字段的值,即所有num字段的值增加1

# Q 构建搜索条件
# filter()中可以传递,k:value, **dict, Q.
from django.db.models import Q
con = Q()  

q1 = Q()
q1.connector = 'OR'  # 下面的条件为或
q1.children.append(('id', 1))
q1.children.append(('id', 10)) 
q1.children.append(('id', 9))

q2 = Q() # q2.connector = 'OR'
q2.children.append(('c1', 1)) 
q2.children.append(('c1', 10)) 
q2.children.append(('c1', 9)) 

con.add(q1, 'AND') # 添加方式为并
con.add(q2, 'AND') 
models.Tb1.objects.filter(con)  # 搜索的结果需要同时满足q1和q2

# 在django里之间使用SQL语句
from django.db import connection
cursor = connection.cursor()
cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
row = cursor.fetchone()

  (3)连表操作

 利用双下划线和_set 将表之间的操作连接起来

# models.py  表结构
class UserProfile(models.Model):
    user_info = models.OneToOneField('UserInfo')
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __unicode__(self):
        return self.username

class UserInfo(models.Model):
    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class UserGroup(models.Model):
    caption = models.CharField(max_length=64)
    user_info = models.ManyToManyField('UserInfo')

    def __unicode__(self):
        return self.caption

class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey('UserGroup')

    def __unicode__(self):
        return self.hostname
View Code
# 一对一操作
user_info_obj = models.UserInfo.objects.filter(id=1).first()  # 获取用户id为1的用户数据
print(user_info_obj.user_type)
print(user_info_obj.get_user_type_display())
print(user_info_obj.userprofile.password)

user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() 
print(user_info_obj.keys())
print(user_info_obj.values())
# 一对多操作
类似一对一
1、搜索条件使用 __ 连接
UserInfo 记录用户name,pwd UserType记录用户类型
models.UserInfo.objects.filter(user_type__name='CEO')  # 获取用户类型是CEO的所有用户信息
2、获取值时使用 .  连接
models.UserInfo.objects.filter(user_type__name='CEO').values('name','pwd','user_type__name')
[{'name':'user1','pwd':'password','user_type__name':'CEO'}]
# 如果将values 换成 value_list,获取的结果将变成元组
[(xx,xx,xx)]
# 多对多操作
# xx_set 中的【_set】是多对多中的固定搭配
user_info_obj = models.UserInfo.objects.get(name=u'小明')
user_info_objs = models.UserInfo.objects.all()

group_obj = models.UserGroup.objects.get(caption='CEO')
group_objs = models.UserGroup.objects.all()

# 添加数据
group_obj.user_info.add(user_info_obj)
group_obj.user_info.add(*user_info_objs)

# 删除数据
group_obj.user_info.remove(user_info_obj)
group_obj.user_info.remove(*user_info_objs)

# 添加数据
user_info_obj.usergroup_set.add(group_obj)
user_info_obj.usergroup_set.add(*group_objs)

# 删除数据
user_info_obj.usergroup_set.remove(group_obj)
user_info_obj.usergroup_set.remove(*group_objs)

# 获取数据
print(group_obj.user_info.all())
print(group_obj.user_info.all().filter(id=1))

# 获取数据
print(user_info_obj.usergroup_set.all())
print(user_info_obj.usergroup_set.all().filter(caption='CEO'))
print(user_info_obj.usergroup_set.all().filter(caption='DBA'))

 

。。

posted @ 2016-09-24 07:44  Auvღ  阅读(698)  评论(0)    收藏  举报