导图社区 模型
关于Django模型的知识结构图,定义模型,Django的orm,自定义原生的sql
编辑于2020-03-08 10:07:41model(模型)
1 开发流程
① Django对各种数据库有比较好的支持,Django为这些数据库提供了统一的调用API
②配置数据库
修改工程目录下的_init_.py文件
import pymysql pymysql.install_as_MySQLdb()
修改settings.py文件
'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '<数据库的名称>', 'USER': '<数据库登录账号>', 'PASSWORD': '<登录密码>', 'HOST': '<IP>', 'PORT': '<端口>' }
③定义模型
一个模型对应数据库中一张表
④生成迁移文件
⑤生成数据表
⑥操作数据(CRUD)
2 定义模型
①模型、属性,表、字段
模型 —> 表;属性—> 字段
②定义属性
①属性命名规则
遵循标志符规则 Django,不允许使用连续的下划线出于 类似的原因,字段名称不能以下划线结尾
②字段类型
AutoField BigAutoField IntegerField (int) BigIntegerField (int) CharField (varchar,textInput) TextField (text,textarea,>4000Byte) DecimalField (decimal,) 表示小数,两个必需的参数,max_digits:总的位数,decimal_places:小数位数 FloatField (float,) BooleanField (tinyint(1),CheckboxInput):True,False NullBooleanField (tinyint(1),CheckboxInput): null,True,False DateField (date,textInput) 日期,在Python中由datetime.date实例表示 TimeField (date,textInput) 时间,在Python中以datetime.time实例表示 DateTimeField (datetime,textInput) 日期和时间,在Python中由datetime.datetime实例表示。接受与相同的额外参数DateField DateField.auto_now 每次保存对象时自动将字段设置为现在。对于“最后修改的”时间戳有用。请注意,始终 使用当前日期。 DateField.auto_now_add 首次创建对象时,将字段自动设置为现在。对于创建时间戳很有用。 于DateField:default=date.today-从 datetime.date.today() 于DateTimeField:default=timezone.now-从 django.utils.timezone.now() default 三个属性不能同时使用 FileField()文件上传 ImageField()图片,继承FileField
③字段类型属性
null: 如果为True,则Django将NULL在数据库中存储空值。默认值为False。 blank: 如果为True,则该字段允许为空白。默认值为False。 db_column: 该字段的数据库列的名称。如果未指定,Django将使用该字段的名称 db_index: 如果为True,将为此字段创建数据库索引 default: 字段的默认值。这可以是值或可调用对象。如果可以调用,则每次创建新对象时都会调用它 primary_key: 若为True,该字段为主键 unique: 如果为True,则该字段在整个表格中必须是唯一的 verbose_name: 该字段的可读名称。如果未提供详细名称,则Django将使用字段的属性名称自动创建,将下划线转换为空格 validators: 要为此字段运行的验证器列表,file:///E:/%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/python/django-docs-3.0-en/ref/validators.html help_text: 额外的“帮助”文本将与表单窗口小部件一起显示。即使您的字段未在表单上使用,它对于文档记录也很有用。请注意,此值未以自动生成的形式转义为HTML。如果需要,可以将HTML包含在内help_text。例如: help_text="Please use the following format: <em>YYYY-MM-DD</em>."或者,您可以使用纯文本并 django.utils.html.escape()转义任何HTML特殊字符
④关系字段
ForeignKey OneToOneField ManyToManyField
③自定义manager类
# 自定义模型管理器,默认的objects就不存在了。一个模型类可以有多个管理器 userInfoObj = models.Manager()
class UserInfoManager(models.Manager): ''' 自定义管理器Manager类 ''' def get_queryset(self): return super(UserInfoManager, self).get_queryset().filter(isDelete=False) # 返回isDelete=false的数据
④自定义Meta类
class Meta: # 定义数据表名,如果不写,默认为:项目名_类名(小写) db_table = "user_info" # 定义排序,查询列表时,默认的排序字段 ordering = ['id', '-createTime'] # 升序,'-id' 降序
⑤在模型类自定义类方法
定义创建模型对象的方法
@classmethod def create_user_info(cls, name, age, desc, money, length): user_info = cls(name=name, age=age, desc=desc, money=money, length=length) return user_info
⑥在自定义manage类中自定义方法
class UserInfoManager(models.Manager): """ 自定义管理器Manager类 """ def get_queryset(self): return super(UserInfoManager, self).get_queryset().filter(isDelete=False) # 返回isDelete=false的数据 def create_user_info2(self, name, age, desc, money, length): """ 在管理器中自定义模型对象的方法 :param name: :param age: :param desc: :param money: :param length: :return: """ # 当前的对象 model = self.model() print(type(model)) model.name = name model.age = age model.desc = desc model.money = money model.length = length return model
3 模型查询
①从数据库获取对象集合
②查询集可以有多个过滤器
③查询集
a.在自定义管理器调用过滤器返回查询集
b.链式过滤器
c.惰性执行:创建查询集不会查询数据库,直到用数据时,才调用数据库
d.直接访问数据库情况
迭代
序列化
与if合用
返回查询集的方法称为过滤器
all()
filter():返回符合条件的数据
filter(键=值,键=值),and
filter(键=值).filter(键=值),and
exclude():返回不符合条件的数据
order_by()
values():返回一个对象(字典)列表
④返回单个数据
get():返回满足调价的对象。如果没有找到符合条件的对象,模型类会抛出一个异常(模型类.ObjectDoesNotExist);如果找到多个对象,也会抛出一个异常(模型类.MultipleObjectsReturned)
count():返回查询集的总数
first():返回查询集第一个对象
last():返回查询集最后一个对象
exists():判断是否有数据
⑤限制查询集
查询集的是列表,通过下标[0:5]取值,但是不能是负数
user_infos = UserInfo.userInfoObj2.all()[(start - 1) * limit:start * limit] # 0-2 2-4 4-6
⑥查询集缓存
每个查询集都有一个缓存,以减少访问数据库的次数
在新建的查询集中首次换粗为空,第一次对查询集访问数据时,将会将数据缓存,并返回查询结果,以后该查询集再次查询时,从缓存中取数据
⑦字段查询
实现sql语句中where语句,方法filter(), exclude()和 get()
属性名__比较运算符=值
主键
转义:like。转义%
比较运算符
exact:完全匹配,区分大小写;iexact:完全匹配,不区分大小写
contains:包含,区分大小写;icontains:包含,不区分大小写。like,'%%'
user_infos = UserInfo.userInfoObj2.all().filter(name__contains='赵')
startswith:以什么开始,区分大小写;istartswith:以什么开始,不区分大小写。'%S'
user_infos = UserInfo.userInfoObj2.all().filter(name__startswith='张')
endswith:以什么结束,区分大小写;endswith:以什么结束,不区分大小写。's%'
isnull:是否为空,True,False。IS NULL
in:是否包含
user_infos = UserInfo.userInfoObj2.all().filter(id__in=[1, 3])
lt:小于,gt:大于;lte:小于等于,gte:大于等于
range:范围,between...and...
user_infos = UserInfo.userInfoObj2.all().filter(age__range=(20, 29))
时间查询
date:精确到日期。filter(createTime__date=datetime.date(2020, 3, 8)) year:精确匹配年份。允许链接其他字段查找(user_infos =filter(createTime__year__gte=2021)) iso_year: month:精确匹配月份。允许链接其他字段查找 day: week: week_day: quarter: time: hour: minute: second:
regex:区分大小写的正则表达式匹配。iregrx:不区分大小写的正则表达式匹配
快捷查询:Django提供了一个pk查找快捷方式,它代表“主键”
聚合查询
Aggregate():通过该函数返回聚合函数的值
Avg():返回给定表达式的平均值,除非您指定了different,否则平均值必须为数字output_field
Count()
Max()
Min()
Sum()
StdDev():标准偏差
Variance():方差
关联查询:jion
# 关联查询,查询年龄大于等于25,并且年龄小于等于30的用户的银行卡信息 bankCard = BankCard.objects.all().filter(userId__age__gte=25, userId__age__lte=30)
F对象
过滤器中的方法:使用模型的A字段与B字段(加,减,乘,除,取模和幂运算)进行比较
可以在查询过滤器中使用这些引用来比较同一模型实例上两个不同字段的值
userInfo = UserInfo.userInfoObj2.all().filter(createTime__date__gt=F('lastTime')).values_list()
Q对象
过滤器方法中的方法:或 or关系
将Q对象与&和|运算符组合在一起并使用括号分组来编写任意复杂度的语句。另外,Q 可以使用~运算符来否定对象,从而允许结合了常规查询和否定(NOT)查询的组合查找
userInfo = UserInfo.userInfoObj2.all().filter(Q(id__lt=2) | Q(age__gt=30)) UserInfo.userInfoObj2.all().filter(Q(id__lt=2) | ~Q(age__gt=30))
⑧原始sql
执行原始查询
Manager.raw(raw_query,params = None,translations = None):方法接受原始SQL查询,执行该查询,然后返回一个 django.db.models.query.RawQuerySet实例
params = { 'id': 2, 'age': 30, 'currentPage': 0, 'pageSize': 5 } param_map = {'id': 'id', 'name': 'name', 'is_delete': 'isDelete'} userInfo = UserInfo.userInfoObj2.raw(''' select `id`,`name` from user_info where id >= %(id)s and age <= %(age)s limit %(currentPage)s,%(pageSize)s ''', params=params, translations=param_map)
直接执行自定义
该对象django.db.connection代表默认的数据库连接。要使用数据库连接,请调用connection.cursor()以获取游标对象。然后,调用以执行SQL和或返回结果行
# 如果您使用多个数据库,则可以用于django.db.connections获取特定数据库的连接(和游标) # with connections['my_db_alias'].cursor() as cursor: with connection.cursor() as cursor: cursor.execute(''' select * from user_info where id >= %s and age <= %s limit %s,%s ''', params=[2, 30, 0, 5]) # data = cursor.fetchall() # (54360982, None), (54360880, None)) # data = dictfetchall(cursor) # [{},{}]字典列表 data = namedtuplefetchall(cursor) # [(),()]元祖列表
def dictfetchall(cursor): """ Return all rows from a cursor as a dict 将游标返回的结果保存到一个字典对象中 """ # return [dict(zip([col[0] for col in cursor.description], row)) for row in cursor.fetchall()] columns = [col[0] for col in cursor.description] # 表中的字段 元祖 return [ dict(zip(columns, row)) for row in cursor.fetchall() ] def namedtuplefetchall(cursor): """Return all rows from a cursor as a namedtuple""" desc = cursor.description nt_result = namedtuple('Result', [col[0] for col in desc]) return [nt_result(*row) for row in cursor.fetchall()]