date: 2021-11-24title: Django之模型层_单表操作 #标题
tags: #标签
categories: python # 分类

ORM简介

  • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
  • ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(和sqlalchemy很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
  • 类对象—->sql—->pymysql—->mysql服务端—->磁盘,orm其实就是将类对象的语法翻译成sql语句的一个引擎,明白orm是什么了,剩下的就是怎么使用orm,怎么来写类对象关系语句。

参考:django模型层ORM
如下是mysql原生语句和ORM的区别:

  1. ######### 原生sql
  2. #创建表:
  3. CREATE TABLE employee(
  4. id INT PRIMARY KEY auto_increment ,
  5. name VARCHAR (20),
  6. gender BIT default 1,
  7. birthday DATA ,
  8. department VARCHAR (20),
  9. salary DECIMAL (8,2) unsigned,
  10. );
  11. # 添加一条记录:
  12. INSERT employee (name,gender,birthday,salary,department)
  13. VALUES ("alex",1,"1985-12-12",8000,"保洁部");
  14. # 查询一条表记录:
  15. SELECT * FROM employee WHERE age=24;
  16. # 更新一条表记录:
  17. UPDATE employee SET birthday="1989-10-24" WHERE id=1;
  18. # 删除一条表记录:
  19. DELETE FROM employee WHERE name="alex"
  20. ######### python的类
  21. '''
  22. # 创建表
  23. (还需要在终端中的项目目录下执行两条命令:python manage.py makemigrations 和 python manage.py migrate)
  24. '''
  25. class Employee(models.Model):
  26. id=models.AutoField(primary_key=True)
  27. name=models.CharField(max_length=32)
  28. gender=models.BooleanField()
  29. birthday=models.DateField()
  30. department=models.CharField(max_length=32)
  31. salary=models.DecimalField(max_digits=8,decimal_places=2)
  32. #python的类对象
  33. # 添加一条表记录:
  34. emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部")
  35. emp.save()
  36. # 查询一条表记录:
  37. Employee.objects.filter(age=24)
  38. # 更新一条表记录:
  39. Employee.objects.filter(id=1).update(birthday="1989-10-24")
  40. # 删除一条表记录:
  41. Employee.objects.filter(name="alex").delete()

好,现在我们就来看看,如何在django项目中连接mysql数据库(默认django会给我们连接一个sqllite3数据库用作测试,不过一般我们不会使用这种数据库,而是使用mysql或oracle等)。

配置django项目连接mysql数据库

安装mysql数据库

参考:windows下安装mysql服务

修改settings.py配置文件

  1. # 默认使用sqlite3数据库,注释相关配置
  2. # DATABASES = {
  3. # 'default': {
  4. # 'ENGINE': 'django.db.backends.sqlite3',
  5. # 'NAME': BASE_DIR / 'db.sqlite3',
  6. # }
  7. # }
  8. # 添加mysql为项目数据库
  9. DATABASES = {
  10. 'default': {
  11. 'ENGINE': 'django.db.backends.mysql', # 指定mysql数据库引擎
  12. 'NAME': 'ljz', # 要连接的数据库名称(需要提前手动创建好)
  13. 'USER': 'root', # 连接数据库的用户
  14. 'PASSWORD': '123.com', # 用户密码
  15. 'HOST': '127.0.0.1', # 数据库地址
  16. 'PORT': 3306 # 数据库连接端口
  17. }
  18. }
  19. ############ 如果要为每个app单独配置数据库,请参考如下配置 #############
  20. '''
  21. DATABASES = {
  22. 'default': {
  23. 'ENGINE': 'django.db.backends.mysql',
  24. 'NAME': 'bms',
  25. 'USER': 'root', # 连接数据库的用户名
  26. 'PASSWORD': '', # 连接数据库的密码
  27. 'HOST': '127.0.0.1', # 连接主机,默认本级
  28. 'PORT': 3306 # 端口 默认3306
  29. },
  30. 'app01': { # 可以为每个app都配置自己的数据,并且数据库还可以指定别的,也就是不一定就是mysql,也可以指定sqlite等其他的数据库
  31. 'ENGINE': 'django.db.backends.mysql',
  32. 'NAME': 'bms', # 要连接的数据库,连接前需要创建好
  33. 'USER': 'root', # 连接数据库的用户名
  34. 'PASSWORD': '', # 连接数据库的密码
  35. 'HOST': '127.0.0.1', # 连接主机,默认本级
  36. 'PORT': 3306 # 端口 默认3306
  37. }
  38. }
  39. '''

设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。然后,启动项目,会报错:django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.Did you install mysqlclient? 。这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb 对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的init,在里面写入:

  1. import pymysql
  2. pymysql.install_as_MySQLdb()

如果你也没有安装pymysql,那么需要在终端下执行如下指令进行安装:

  1. $ pip3 install pymysql

至此,我们就可以正常启动项目了,启动后,控制台输出无异常,表示项目启动成功。

编写moudels.py文件

现在来写下moudels.py文件:

  1. from django.db import models
  2. # Create your models here.
  3. from django.db import models
  4. class UserInfo(models.Model):
  5. id = models.AutoField(primary_key=True)
  6. name = models.CharField(max_length=16, null=True, blank=True)
  7. age = models.IntegerField()
  8. current_date = models.DateField()
  9. '''
  10. 上面定义的UserInfo类,就相当于下面这条sql语句
  11. # create table userinfo(id int primary key auto_increment,name varchar(16),age int,current_date date ))
  12. '''

现在我们运行项目管理工具,将上面的sql写入数据库中。

项目sql写入数据库中

在pycharm界面按下Ctrl+Alt+R建,运行manage.py脚本,然后输入如下:

  1. $ makemigrations
  2. $ migrate

上面两条指令,直接执行manage.py脚本的话,需要使用如下指令:

  1. '''生成记录,每次修改了models里面的内容或者添加了新的app,
  2. 新的app里面写了models里面的内容,都要执行这两条
  3. '''
  4. python manage.py makemigrations
  5. python manage.py migrate
  6. '''
  7. 执行上面这个语句的记录来创建表,生成的表名字前面会自带应用的名字,
  8. 例如:你的book表在mysql里面叫做app01_book表
  9. '''

在执行 python manager.py magrations 时django 会在相应的 app 的migration文件夹下面生成 一个python脚本文件,在执行 python manager.py migrte 时 django才会生成数据库表,那么django是如何生成数据库表的呢?django是根据 migration下面的脚本文件来生成数据表的,每个migration文件夹下面有多个脚本,那么django是如何知道该执行那个文件的呢,django有一张django-migrations表,表中记录了已经执行的脚本,那么表中没有的就是还没执行的脚本,则 执行migrate的时候就只执行表中没有记录的那些脚本。有时在执行 migrate 的时候如果发现没有生成相应的表,可以看看在 django-migrations表中看看 脚本是否已经执行了,可以删除 django-migrations 表中的记录 和 数据库中相应的 表 , 然后重新执行。

运行界面如下:

Django之模型层_单表操作 - 图1

如上所示,运行完成,无报错信息,现在可以自行去数据库中进行查看,moudels.py文件中定义的类,是否正确的在数据库中创建了表,我这边查到的表信息如下:

Django之模型层_单表操作 - 图2

models字段和参数

字段

  1. - CharField:字符串字段, 用于较短的字符串,CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数。
  2. - IntegerField:用于保存一个整数
  3. - DecimalField:一个浮点数。必须 提供两个参数: max_digits(总位数(不包括小数点和符号))和 decimal_places(小数位数),举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段: models.DecimalField(..., max_digits=5, decimal_places=2);要保存最大值一百万(小数点后保存10位)的话,你要这样定义: models.DecimalField(..., max_digits=17, decimal_places=10) #max_digits大于等于17就能存储百万以上的数了
  4. - AutoField:一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 自定义一个主键:my_id=models.AutoField(primary_key=True), 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model
  5. - BooleanFieldA true/false field. admin checkbox 来表示此类字段.
  6. - TextField:一个容量很大的文本字段.。 admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
  7. - EmailField:一个带有检查Email合法性的 CharField,不接受 maxlength 参数。
  8. - DateField:一个日期字段. 共有下列额外的可选参数: auto_now 当对象被保存时(更新或者添加都行),自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳);auto_now_add( 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间。 )
  9. - DateTimeField:一个日期时间字段. 类似 DateField 支持同样的附加选项.
  10. - ImageField:类似 FileField, 不过要校验上传对象是否是一个合法图片,它有两个可选参数:height_fieldwidth_field, 如果提供这两个参数,则图片将按提供的高度和宽度规格保存。

参数

  • null:如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
  • blank:如果为True,该字段允许不填。默认为False。要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
  • default:字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
  • primary_key:如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。
  • unique:如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
  • choices:由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,
    而且这个选择框的选项就是choices 中的选项。
  • db_index:如果db_index=True 则代表着为此字段设置数据库索引。DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
  • auto_now_add:配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
  • auto_now:配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。

增删改查

在进行增删改查测试时,都是写一个视图函数,增删改查相关操作,都是写在这个视图函数中,然后访问此页面,这样访问一下,就执行了这个视图函数的内容。

  1. from django.shortcuts import render
  2. from app01 import models
  3. def index(request):
  4. '''
  5. # 创建记录的方式一(下面的代码写好后,只要访问下index这个视图函数,
  6. #下面的代码就执行了,相应数据也就写入到mysql中了)
  7. userinfo_obj=models.UserInfo(name='吕建钊',age=25)
  8. userinfo_obj.save() # 上面的方式写入后,需要执行save方法,以便写入到数据库中(就是pymysql的那个commit提交)
  9. # 创建记录的方式二
  10. new_obj=models.UserInfo.objects.create(name='尼古拉斯·赵四',age=44)
  11. # 或者可以写成**{'name':'xx','age':18},create方法是用**kwargs进行接收参数的。
  12. print(new_obj) #输出:UserInfo object (2),UserInfo object也叫做 model对象
  13. print(new_obj.name) #输出:尼古拉斯·赵四,点(.)属性,可以获取对应字段的数据
  14. print(new_obj.age) # 输出 44
  15. # 创建方式三(批量创建)
  16. objs_list = []
  17. for i in range(20, 30):
  18. obj = models.UserInfo(
  19. name='张三_'+str(i),
  20. age=10+i,
  21. )
  22. objs_list.append(obj)
  23. models.UserInfo.objects.bulk_create(objs_list)
  24. '''
  25. #创建方法四:update_or_create(有就更新, 没有就创建)
  26. models.UserInfo.objects.update_or_create(
  27. name='张三',
  28. defaults={
  29. 'age': 228,
  30. }
  31. )
  32. return render(request, 'index.html')

下面有些查询方法,总说在表对象中定义了__str__方法,怕日后忘记,这里着重说下,就是如下:

Django之模型层_单表操作 - 图3

如下,是对__str__方法的解释:

Django之模型层_单表操作 - 图4

好,接下来,我们来对数据库进行查操作。

  1. from django.shortcuts import render
  2. from app01 import models
  3. def index(request):
  4. '''
  5. ####### 条件查询:.filter方法,返回的也是queryset集合,
  6. # 查询不到内容,不会报错,返回一个<QuerySet []>空的queryset
  7. objs = models.UserInfo.objects.filter(id=2) #找id为2的那条记录
  8. for i in objs:
  9. print(i.name)
  10. print(i.age)
  11. 如果不想使用for进行取值,可以在modules.py的表对象中定义__str__方法,返回固定的字段值,如下:
  12. def __str__(self):
  13. return self.name
  14. ###### filter多条件查询
  15. objs = models.UserInfo.objects.filter(name='吕建钊',id=1)
  16. print(objs)
  17. 如果在表类对象中定义了__str__方法,如下:
  18. def __str__(self):
  19. return self.name
  20. 则上面的print输入:<QuerySet [<UserInfo: 吕建钊>]>
  21. '''
  22. ###### get方法查询:返回的是model对象,而且get方法有且必须只有1个结果,否则报错
  23. obj = models.UserInfo.objects.get(id=13)
  24. print(obj) # 输出 张三(在表对象中定义了__str__方法)
  25. return render(request, 'index.html')

查询接口
  • all(): 查询所有结果,结果是queryset类型。
  • filter(**kwargs): 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title=’linux’,price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系。
  1. models.Student.objects.filter(id=7,name='大壮哥哥',age=78).update(
  2. name='大壮禅师',
  3. age=78
  4. )
  5. #打散形式传参
  6. models.Student.objects.filter(**{'id':7,'name':'大壮禅师'}).update(age=100)
  7. models.Student.objects.all().filter(id=7) # queryset类型可以调用fitler在过滤
  • get(**kwargs): 返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 Book.objects.get(id=1)。
  • exclude(**kwargs): 排除的意思,它包含了与所给筛选条件不匹配的对象,用这个exclude,返回值是queryset类型,如:Book.objects.exclude(id=6)的执行结果,返回id不等于6的所有的对象,或者在queryset基础上调用,如:Book.objects.all().exclude(id=6)。
  1. exclude(**kwargs): # 排除,objects控制器和queryset集合都可以调用,返回结果是queryset类型
  2. query = models.Student.objects.exclude(id=1)
  3. print(query)
  4. query = models.Student.objects.filter(age=38).exclude(id=6)
  5. print(query)
  • order_by(*field): queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型,如:models.Book.objects.all().order_by(‘price’,’id’) ,直接写price,默认是按照price升序排列,如果想按照字段降序排列,就写个负号就行了order_by(‘-price’)。order_by(‘price’,’id’)是多条件排序,按照price进行升序,price相同的数据,按照id进行升序。
  • reverse(): queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型。
  1. # 排序之后反转
  2. query = models.Student.objects.all().order_by('id').reverse()
  3. print(query)
  • count(): queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
  • first(): queryset类型的数据来调用,返回第一条记录 Book.objects.all()[0] = Book.objects.all().first(),得到的都是model对象,不是queryset。
  • last(): queryset类型的数据来调用,返回最后一条记录
  • exists(): queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False。空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits,例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS a FROM app01_book LIMIT 1,就是通过limit 1,取一条来看看是不是有数据。
  • values(*field): 用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
  • values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列。
  • distinct(): values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复记录。

关于上面的values、values_list、distinct方法用法示例如下:

  1. from django.shortcuts import render
  2. from app01 import models
  3. def index(request):
  4. obj = models.UserInfo.objects.values('name', 'age')
  5. print(obj) # 返回 <QuerySet [{'name': '张三', 'age': 67}, {'name': '尼古拉斯·赵四', 'age': 67}]>
  6. obj_2 = models.UserInfo.objects.values('name') # 返回:<QuerySet [{'name': '张三'}, {'name': '尼古拉斯·赵四'}]>
  7. print(obj_2)
  8. obj_3 = models.UserInfo.objects.values_list('name', 'age') # 返回 <QuerySet [('张三', 67), ('尼古拉斯·赵四', 67)]>
  9. print(obj_3)
  10. obj_4 = models.UserInfo.objects.values_list('name')
  11. print(obj_4) # 返回 [('张三',), ('尼古拉斯·赵四',)]>
  12. # 下面有些数据是重复的
  13. obj_5 = models.UserInfo.objects.values_list('name','age').distinct() # 返回<QuerySet [('张三', 67), ('尼古拉斯·赵四', 67), ('吕建钊', 18)]>
  14. print(obj_5)
  15. return render(request, 'index.html')

基于双下划线的模糊查询

注意:我在models.py文件中定义了__str__方法:

  1. def __str__(self):
  2. return self.name

下面是一些模糊查询的示例:

  1. # 查询id大于41的
  2. querey=models.UserInfo.objects.filter(id__gt=41) # 输出:<QuerySet [<UserInfo: 尼古拉斯·赵四>, <UserInfo: 吕建钊>]>
  3. print(querey)
  4. # 查询id大于或等于41的
  5. querey_2 = models.UserInfo.objects.filter(id__gte=41) # 输出:[<UserInfo: 张三>, <UserInfo: 尼古拉斯·赵四>, <UserInfo: 吕建钊>]>
  6. print(querey_2)
  7. # 查询id小于37的
  8. querey_3 = models.UserInfo.objects.filter(id__lt=37) # 输出:<QuerySet [<UserInfo: 张三>, <UserInfo: 尼古拉斯·赵四>, <UserInfo: 尼古拉斯·赵四>]>
  9. print(querey_3)
  10. # 查询id小于或等于37的
  11. querey_4 = models.UserInfo.objects.filter(id__lte=37) # 输出:<QuerySet [<UserInfo: 张三>, <UserInfo: 尼古拉斯·赵四>, <UserInfo: 尼古拉斯·赵四>, <UserInfo: 尼古拉斯·赵四>]>
  12. print(querey_4)
  13. # 查询id小于等于42并大于或等于39(相当于sql中的between and)
  14. querey_5 = models.UserInfo.objects.filter(id__range=[39,42])
  15. print(querey_5)
  16. # 查询id等于这个列表中的任意一个值得对象,也就是查询id为34或者42、43的记录
  17. querey_6 = models.UserInfo.objects.filter(id__in=[34,42,43])
  18. print(querey_6)
  19. # 查询name列包含“张”字的列
  20. querey_7 = models.UserInfo.objects.filter(name__contains='张')
  21. print(querey_7)
  22. # # 查询class列包含“py”的列(不区分大小写)
  23. # querey_8 = models.UserInfo.objects.filter(name__icontains='py')
  24. # print(querey_8)
  25. # # 查询class列中以“py”开头的列(如果想不区分大小写,请将startswith改为istartswith)
  26. # querey_9 = models.UserInfo.objects.filter(name__startswith='py')
  27. # print(querey_9)

下面来一些关于日期的模糊查询。

可以先使用下面的代码,创建出需要的源数据:

############   models.py文件内容
from django.db import models

class Brithday(models.Model):
    name=models.CharField(max_length=13)
    date=models.DateField()
    def __str__(self):
        return self.name



############  views.py文件内容
from django.shortcuts import render
from app01 import models


def index(request):
    # import datetime
    # current_date=datetime.datetime.now()   # 2021-11-17 11:43:20.375682
    obj = models.Brithday.objects
    # obj.create(name='吕建钊',date=current_date)
    # obj.create(name='张三_0', date='2000-11-11')
    # obj.create(name='张三_1',date='2000-11-15')
    # obj.create(name='张三_2',date='2000-12-15')
    # obj.create(name='张三_3',date='2000-12-6')
    # obj.create(name='张三_4',date='2000-12-8')
    # obj.create(name='张三_5', date='2001-12-6')
    # obj.create(name='张三_6', date='2002-12-6')
    # obj.create(name='张三_7', date='2003-12-6')

日期查询示例如下:

from django.shortcuts import render
from app01 import models


def index(request):
    obj = models.Brithday.objects

    # 查询2000年出生的张三
    query_1 = obj.filter(date__year='2000')
    print(query_1)

    # 查询2000年12月出生的张三
    query_2 = obj.filter(date__year='2000', date__month='12')
    print(query_2)

    # 查询大于2000年出生的张三
    query_3 = obj.filter(date__year__gt='2000')
    print(query_3)

    # 查询大于2000年12月6日出生的人
    query_4 = obj.filter(date__year='2000', date__month='12', date__day__gt='06')
    print(query_4)
    return render(request, 'index.html')

from django.shortcuts import render
from app01 import models


def index(request):
    '''
    ###### get方法,先查出来,再调用delete方法进行删除
    models.UserInfo.objects.get(id=13).delete()

    ###### filter方法先查出来再删
    #(和get方法类似,只是就算没有匹配上也不会报错,
    # 而get方法会报错,filter也可以查出来多个,一次删除,
    # 而get方法不可以)
    # models.UserInfo.objects.filter(id=13).delete()
    '''


    ###### all方法,删除所有数据
    models.UserInfo.objects.all().delete()
    return render(request, 'index.html')

更新 update方法 model对象不能调用更新方法 报错信息’Student’ object has no attribute ‘update’,只能queryset调用,如下:

from django.shortcuts import render
from app01 import models


def index(request):
    # filter:先查出来,再update
    models.UserInfo.objects.filter(name='尼古拉斯·赵四').update(age=67)
    return render(request, 'index.html')

打印orm转换过程中的sql

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

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

我试过上面的配置,如果是filter查询,则需要打印查询结果,才可以在控制台打印出相关sql查询语句,具体自行琢磨吧。

或者可以使用下面的方法查询:

from django.shortcuts import render
from app01 import models


def index(request):
    # 添加记录
    obj = models.UserInfo(name='吕建钊', age=18)
    obj.save()
    from django.db import connection  # 通过这种方式也能查看执行的sql语句
    print(connection.queries)

    return render(request, 'index.html')

外部文件操作django的models

参考:外部文件操作django的models

有时候,我们写好项目代码后,可能还想通过单独的py文件去调用项目中的models文件,去连接数据库,这里就写下如何配置它。

# 首先在项目目录下随便新建一个py文件,内容如下:

import os


def main():
    # 加载django环境(下面加载环境的代码是从项目目录下的manage.py文件中copy过来的)
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books_Admin_system.settings')
    import django
    # 启动django环境
    django.setup()

    # 启动django后,就可以引入应用的models模块了
    from Books_Manager import models

    # 引入模块后,就可以操作数据库了
    obj_list = []
    for i in range(1, 10):
        obj = models.books(
            book_name=f'降龙十八掌第{i}式',
            price=20 + i,
            date=f'198{i}-11-11',
            press='张三丰出版社'
        )
        obj_list.append(obj)
    models.books.objects.bulk_create(obj_list)


if __name__ == '__main__':
    main()

运行上面的代码,就可以将数据写入到项目的数据库中了。

django项目中的时区问题

不是跨时区的应用,不需要考虑时区问题,就将USE_TZ这个值改为False,mysql是对时区不敏感,django往mysql里面出数据的时候,如果这个值为True,那么将让mysql强制使用UTC时间,那么我们存储进入的时间,当你查询的时候,你就会发现,时间晚了8小时,也就是说你存时间的时候被改为了UTC时间,本地是东八区,比UTC时间多8小时。

# settings.py文件中的配置

# Django1.9以后 'zh-cn'就被丢弃了,使用'zh-hans'代替。
LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False