Django 模型ORM
阅读原文时间:2023年07月10日阅读:2

from django.db import models

Create your models here.

class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
create_time = models.DateTimeField()
price = models.DecimalField(decimal_places=2, max_digits=8)

3.1 模型类属性命名限制

1)不能是python的保留关键字。

2)不允许使用连续的下划线,这是由django的查询方式决定的。

3)定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:

属性名=models.字段类型(选项)

3.2 字段类型

类型

描述

AutoField

自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。

BooleanField

布尔字段,值为True或False。

NullBooleanField

支持Null、True、False三种值。

CharField(max_length=最大长度)

字符串。参数max_length表示最大字符个数。

必须设置该属性

TextField

大文本字段,一般超过4000个字符时使用。

IntegerField

整数

DecimalField(max_digits=None, decimal_places=None)

十进制浮点数。参数max_digits表示总位。参数decimal_places表示小数位数。

FloatField

浮点数。参数同上

DateField([auto_now=False, auto_now_add=False])

日期。

1)参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。

2) 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。

3)参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。

TimeField

时间,参数同DateField。

DateTimeField

日期时间,参数同DateField。

FileField

上传文件字段。

ImageField

继承于FileField,对上传的内容进行校验,确保是有效的图片。

选项

通过选项实现对字段的约束,选项如下:

选项名

描述

default

默认值。设置默认值。

primary_key

若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。

unique

如果为True, 这个字段在表中必须有唯一值,默认值是False。

db_index

若值为True, 则在表中会为此字段创建索引,默认值是False。

db_column

字段的名称,如果未指定,则使用属性的名称。

null

如果为True,表示允许为空,默认值是False。

blank

如果为True,则该字段允许为空白,默认值是False。

对比:null是数据库范畴的概念,blank是后台管理(admin)页面表单验证范畴的。

经验:

当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移。

settings配置

若想将模型转为mysql数据库中的表,需要在settings中配置:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'bms',      # 要连接的数据库,连接前需要创建好
'USER':'root',       # 连接数据库的用户名
'PASSWORD':'',       # 连接数据库的密码
'HOST':'127.0.0.1', # 连接主机,默认本级
'PORT':3306     # 端口 默认3306
}
}

注意1:NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 USER和PASSWORD分别是数据库的用户名和密码。设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。然后,启动项目,会报错:no module named MySQLdb 。这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb 对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的__init__,在里面写入:

1

2

import pymysql

pymysql.install_as_MySQLdb()

最后通过两条数据库迁移命令即可在指定的数据库中创建表 :

1

2

python manage.py makemigrations

python manage.py migrate

注意2:确保配置文件中的INSTALLED_APPS中写入我们创建的app名称

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"book"
]

注意3:如果报错如下:

1

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3``.``3 or newer is required; you have 0.7``.``11.None

MySQLclient目前只支持到python3.4,因此如果使用的更高版本的python,需要修改如下:

通过查找路径C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql
这个路径里的文件把

1

2

if version < (``1``, 3``, 3``):

raise ImproperlyConfigured(``"mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

注释掉 就OK了。

注意4: 如果想打印orm转换过程中的sql,需要在settings中进行如下配置:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

LOGGING = {

'version'``: 1``,

'disable_existing_loggers'``: False``,

'handlers'``: {

'console'``:{

'level'``:``'DEBUG'``,

'class'``:``'logging.StreamHandler'``,

},

},

'loggers'``: {

'django.db.backends'``: {

'handlers'``: [``'console'``],

'propagate'``: True``,

'level'``:``'DEBUG'``,

},

}

}

方式1

# create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象

book_obj``=``Book.objects.create(title``=``"python葵花宝典"``,state``=``True``,price``=``100``,publish``=``"苹果出版社"``,pub_date``=``"2012-12-12"``)

方式2

1

2

book_obj``=``Book(title``=``"python葵花宝典"``,state``=``True``,price``=``100``,publish``=``"苹果出版社"``,pub_date``=``"2012-12-12"``)

book_obj.save()

def orm_demo(request):
if request.method == "GET":
return render(request, 'base.html')
if request.method == "POST":
dict_all = request.POST.dict()
** dict_all.pop('csrfmiddlewaretoken') # del dict_all['csrfmiddlewaretoken']* print(dict_all) #这种方法可以不用挨个取参数 ** Book.objects.create(**dict_all)* return HttpResponse('ok')

删除方法就是 delete()。它运行时立即删除对象而不返回任何值。例如:

1

model_obj.delete()

你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。

例如,下面的代码将删除 pub_date 是2005年的 Entry 对象:

1

Entry.objects.``filter``(pub_date__year``=``2005``).delete()

在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:

1

2

3

b = Blog.objects.get(pk``=``1``)

# This will delete the Blog and all of its Entry objects.

b.delete()

要注意的是: delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:

1

Entry.objects.``all``().delete()

如果不想级联删除,可以设置为:

1

pubHouse = models.ForeignKey(to``=``'Publisher'``, on_delete``=``models.SET_NULL, blank``=``True``, null``=``True``)

1

Book.objects.``filter``(title__startswith``=``"py"``).update(price``=``120``)