一 ORM介绍

Django提供了一个抽象层("Model")来构建和管理Web应用程序的数据。

Django使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM):

  • 每个模型就是一个Python类,它继承于django.db.models.Model,对应关系:类名 —> 数据库表名
  • 模型中的每个属性代表一个数据库字段,对应关系:类属性 –> 数据库中的字段
  • 其他:类实例 –> 数据库表中的一行数据obj.xx –> 类实例对象的属性

ORM两大功能:

  • 操作表:增删改
  • 操作数据行:增删改查

注:Django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

Django ORM的优势:

Django的ORM操作本质上会根据对接的数据库引擎,翻译成对应的sql语句;所有使用Django开发的项目无需关心程序底层使用的是MySQL、Oracle、sqlite....,如果数据库迁移,只需要更换Django的数据库引擎即可

二 字段

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

AutoField(Field)      		#int自增列,必须填入参数 primary_key=True		***
BigAutoField(AutoField)         #bigint自增列,必须填入参数 primary_key=True
	注:如果model中没有自增列,则自动会创建一个列名为id的列
	from django.db import models

	class UserInfo(models.Model):
		# 自动创建一个列名为id的且为自增的整数列
		username = models.CharField(max_length=32)

	class Group(models.Model):
		# 自定义自增列
		nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)

CharField(Field)				#字符类型,必须提供max_length参数, max_length表示字符长度		***

TextField(Field)				#文本类型

#字符串类
EmailField(CharField): 		        #Django Admin以及ModelForm中提供验证机制

IPAddressField(Field)			#Django Admin以及ModelForm中提供验证 IPV4 机制

URLField(CharField) 			#Django Admin以及ModelForm中提供验证 URL

SlugField(CharField)			#Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

CommaSeparatedIntegerField(CharField)	#格式必须为逗号分割的数字

UUIDField(Field)		        #Django Admin以及ModelForm中提供对UUID格式的验证

GenericIPAddressField(Field)	        #Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
	- 参数:
		protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
		unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"

FilePathField(Field)			#Django Admin以及ModelForm中提供读取文件夹下文件的功能
	- 参数:
		path,                      文件夹路径
		match=None,                正则匹配
		recursive=False,           递归下面的文件夹
		allow_files=True,          允许文件
		allow_folders=False,       允许文件夹

FileField(Field) 				#路径保存在数据库,文件上传到指定目录
	- 参数:
		upload_to = ""      上传文件的保存路径
		storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

ImageField(FileField)			#路径保存在数据库,文件上传到指定目录
	- 参数:
		upload_to = ""      上传文件的保存路径
		storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
		width_field=None,   上传图片的高度保存的数据库字段名(字符串)
		height_field=None   上传图片的宽度保存的数据库字段名(字符串)

#数字类
SmallIntegerField(IntegerField):	#小整数 -32768 ~ 32767

PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)		#正小整数 0 ~ 32767

IntegerField(Field)		        #整数列(有符号的) -2147483648 ~ 2147483647			***

PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)		#正整数 0 ~ 2147483647

BigIntegerField(IntegerField):		#长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

DurationField(Field)		        #长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

FloatField(Field)			#浮点型			***

BinaryField(Field)			#二进制类型

DecimalField(Field)			#10进制小数		***
	- 参数:
		max_digits,小数总长度
		decimal_places,小数位长度

#布尔值类
BooleanField(Field)

#可以为空的布尔值
NullBooleanField(Field):

#时间类
DateTimeField(DateField)		#日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]   ***

DateField(DateTimeCheckMixin, Field)	#日期格式      YYYY-MM-DD

TimeField(DateTimeCheckMixin, Field)		#时间格式      HH:MM[:ss[.uuuuuu]]

字段列表

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

#枚举类型适用于选项固定的情况
color_list = (
	(1,'黑色'),
	(2,'白色'),
	(3,'蓝色')
)
color = models.IntegerField(choices=color_list)

枚举

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

class UnsignedIntegerField(models.IntegerField):
    def db_type(self, connection):
        return 'integer UNSIGNED'

PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',

自定义无符号整数字段

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

1.触发Model中的验证和错误提示有两种方式:
	a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
	b. 使用ModelForm
	c. 调用Model对象的 clean_fields 方法,如:
		# models.py
		class UserInfo(models.Model):
			nid = models.AutoField(primary_key=True)
			username = models.CharField(max_length=32)

			email = models.EmailField(error_messages={'invalid': '格式错了.'})

		# views.py
		def index(request):
			obj = models.UserInfo(username='11234', email='uu')
			try:
				print(obj.clean_fields())
			except Exception as e:
				print(e)
			return HttpResponse('ok')

	   # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。

2.Admin中修改错误提示
	# admin.py
	from django.contrib import admin
	from model_club import models
	from django import forms

	class UserInfoForm(forms.ModelForm):
		age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})

		class Meta:
			model = models.UserInfo
			# fields = ('username',)
			fields = "__all__"
			exclude = ['title']
			labels = { 'name':'Writer', }
			help_texts = {'name':'some useful help text.',}
			error_messages={ 'name':{'max_length':"this writer name is too long"} }
			widgets={'name':Textarea(attrs={'cols':80,'rows':20})}

	class UserInfoAdmin(admin.ModelAdmin):
		form = UserInfoForm

	admin.site.register(models.UserInfo, UserInfoAdmin)

注意事项

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

models.CharField  对应的是MySQL的varchar数据类型
char 和 varchar的区别 :
char和varchar的共同点是存储数据的长度,不能 超过max_length限制,
不同点是varchar根据数据实际长度存储,char按指定max_length()存储数据;所有前者更节省硬盘空间;

扩展1

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

在数据库存储枚举类型,比外键有什么优势?
1、无需连表查询性能低,省硬盘空间(选项不固定时用外键)
2、在modle文件里不能动态增加(选项一成不变用Django的choice)

扩展2

三 字段参数

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

null                数据库中字段是否可以为空
    db_column           数据库中字段的列名
    default             数据库中字段的默认值
    primary_key         数据库中字段是否为主键
    db_index            数据库中字段是否可以建立索引
    unique              数据库中字段是否可以建立唯一索引
    unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
    unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
    unique_for_year     数据库中字段【年】部分是否可以建立唯一索引

    verbose_name        Admin中显示的字段名称
    blank               Admin中是否允许用户输入为空
    editable            Admin中是否可以编辑
    help_text           Admin中该字段的提示信息
    choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
                        如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)

    error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
                        字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                        如:{'null': "不能为空.", 'invalid': '格式错误'}

    validators          自定义错误验证(列表类型),从而定制想要的验证规则
                        from django.core.validators import RegexValidator
                        from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
                        MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                        如:
                            test = models.CharField(
                                max_length=32,
                                error_messages={
                                    'c1': '优先错信息1',
                                    'c2': '优先错信息2',
                                    'c3': '优先错信息3',
                                },
                                validators=[
                                    RegexValidator(regex='root_\d+', message='错误了', code='c1'),
                                    RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
                                    EmailValidator(message='又错误了', code='c3'), ]
                            )

参数列表

四 元信息

Django ORM用什么mysql django的orm_django

Django ORM用什么mysql django的orm_数据库_02

class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)

            # admin中显示的表名称
            verbose_name

            # verbose_name加s
            verbose_name_plural

View Code

更多请参考:https://docs.djangoproject.com/en/1.10/ref/models/options/

五  数据库设置--MySQL

Django中默认数据库为SQLlite,settings.py内设置如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

所以,如果我们需要变更为MySQL。同时,又因为Django内部连接mysql时使用的是MySQLdb,而py3中还没有此模块,所以需要需要pymysql来代替。具体设置步骤如下:

第一步:创建数据库

由于Django自带的ORM是data_first类型的ORM,使用前必须先创建数据库,创建时注意设置数据的字符编码。

第二步:在settings.py中将DATABASES做如下设置以连接MySQL数据库:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'test11',                               # 数据库名称
        'USER': 'root',                                # 用户名
        'PASSWORD': '',                                # 密码
        'HOST': 'localhost',                           # 主机位置
        'PORT': 3306,                                  # 端口
        }
}

扩展知识:如我们需要查看ORM操作执行的原生SQL语句,我们可以在settings.py中增加以下代码:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

第三步:在同工程名下的__init__文件中设置Django默认连接MySQL的方式:

import pymysql
pymysql.install_as_MySQLdb()

六  创建数据表

第一步:在相应app文件夹中的modals.py进行数据库类创建

from django.db import models

class UserGroup(models.Model):
    """部门"""
    department = models.CharField(max_length=32)

class UserInfo(models.Model):
    """员工"""
    uid = models.AutoField(primary_key=True)            # 若无指定,Django为默认生成以id命名的一列自增数据
    username = models.CharField(max_length=32)          # 必须指定长度
    password = models.CharField(max_length=64)
    age = models.IntegerField(default=1)
    ug = models.ForeignKey("UserGroup",null=True)       # 生成数据库后,列名称变更为ug_‘外键表的id’

第二步:在settings.py文件中注册app文件

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',            # 以上为默认
    'app01',
]

注:Django新版本已经进行该步,我们不需要再进行该操作。

第三步:进行数据迁移。在终端输入以下命令(如需进行表格修改,重新执行该命令):

python manage.py makemigrations
python manage.py migrate

注:我们需要更新或修改字段时,也需要执行以上代码

在执行第三步时,应用外键行可能出现如下错误:

TypeError: __init__() missing 1 required positional argument: 'on_delete'

解决办法:

ug=models.ForeignKey('UserGroup',on_delete=models.CASCADE,)  # 即在外键值的后面加上 on_delete=models.CASCADE

注意:在我们修改数据表结构时,如果新增一个字段,需要设置其为空或者给其设置默认值,否则会报错。

另外,可能会报以下错误:

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

解决办法:

找到python安装环境或项目虚拟环境路径下的:...\Lib\site-packages\django\db\backends\mysql\base.py文件将以下代码注释掉。

if version < (1, 3, 13):
    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)