1 modle 基本数据类型
- class Test(models.Model):
- """测试学习用"""
- Auto = models.AutoField() # 自增长字段
- BigAuto = models.BigAutoField()
- # 二进制数据
- Binary = models.BinaryField()
- # 布尔型
- Boolean = models.BooleanField()
- NullBoolean = models.NullBooleanField()
- # 整型
- PositiveSmallInteger = models.PositiveSmallIntegerField(db_column="age") # 5 个字节
- SmallInteger = models.SmallIntegerField(primary_key=False) # 6 个字节
- PositiveInteger = models.PositiveIntegerField() # 10 个字节
- Integer = models.IntegerField(verbose_name="11 个字节大小") # 11 个字节
- BigInteger = models.BigIntegerField(unique=True) # 20 个字节
- # 字符串类型
- Char = models.CharField(max_length=100, null=True, blank=True, db_index=True) # varchar
- Text = models.TextField(help_text="这个是 longtext") # longtext
- # 时间日期类型
- Date = models.DateField(unique_for_date=True, auto_now=True)
- DateTime = models.DateTimeField(editable=False, unique_for_month=True, auto_now_add=True)
- Duration = models.DurationField() # int, Python timedelta 实现
- # 浮点型
- Float = models.FloatField()
- Decimal = models.DecimalField(max_digits=4, decimal_places=2) # 11.22, 16.34
- # 其它字段
- Email = models.EmailField() # 邮箱
- Image = models.ImageField()
- File = models.FileField()
- FilePath = models.FilePathField()
- URL = models.URLField()
- UUID = models.UUIDField()
- GenericIPAddress = models.GenericIPAddressField()
- View Code
2 modle 的 外键
主要有三类: 一对一 models.OneToOneField (如一个表字段太多, 有些字段平时不怎们用到, 可利用外键将其另建表关联) , 一对多 models.ForeignKey ( 如老师对课程 ) , 多对多 models.ManyToManyField ( 如学生对课程 )
- class A(models.Model):
- onetoone = models.OneToOneField(Test, related_name="one")
- class B(models.Model):
- foreign = models.ForeignKey(A, on_delete=models.CASCADE) # 删除级联
- foreign = models.ForeignKey(A, on_delete=models.PROTECT)
- foreign = models.ForeignKey(A, on_delete=models.SET_NULL, null=True, blank=True) # 删除置空
- foreign = models.ForeignKey(A, on_delete=models.SET_DEFAULT, default=0) #外键删除之后设置默认值, 必须设置默认值
- foreign = models.ForeignKey(A, on_delete=models.DO_NOTHING) #什么也不做
- foreign = models.ForeignKey(A, on_delete=models.SET)
- class C(models.Model):
- manytomany = models.ManyToManyField(B)
- # 1. 所有字段都有的参数
- # 2. 个别字段才有的参数
- # 3. 关系型字段的参数
- """
- on_delete 当一个被外键关联的对象被删除时, Django 将模仿 on_delete 参数定义的 SQL 约束执行相应操作
- 如下 6 种操作
- CASCADE: 模拟 SQL 语言中的 ON DELETE CASCADE 约束, 将定义有外键的模型对象同时删除!(该操作为当前 Django 版本的默认操作!)
- PROTECT: 阻止上面的删除操作, 但是弹出 ProtectedError 异常
- SET_NULL: 将外键字段设为 null, 只有当字段设置了 null=True 时, 方可使用该值.
- SET_DEFAULT: 将外键字段设为默认值. 只有当字段设置了 default 参数时, 方可使用.
- DO_NOTHING: 什么也不做.
- SET(): 设置为一个传递给 SET() 的值或者一个回调函数的返回值. 注意大小写.
- """
- View Code
补充: 自关联时, 传入的类名为 self,
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自关联")
3 modle 的 元数据 Meta
- class AddressInfo(models.Model): # coures_addressinfo
- """省市县地址信息"""
- address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
- pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自关联")
- # pid = models.ForeignKey('AddressInfo', null=True, blank=True, verbose_name="自关联")
- note = models.CharField(max_length=200, null=True, blank=True, verbose_name="说明")
- def __str__(self): # __unicode__(self)
- return self.address
- class Meta:
- # 定义元数据
- db_table = 'address'
- # ordering = ['pid'] # 指定按照什么字段排序
- verbose_name = '省市县地址信息'
- verbose_name_plural = verbose_name
- # abstract = True
- # permissions = (('定义好的权限', '权限说明'),)
- # managed = False
- unique_together = ('address', 'note') # ((),())
- # app_label = 'courses'
- # db_tablespace # 定义数据库表空间的名字
- View Code
补充
1 也可以在 modle 类中自定义函数 可以调用这些函数方法实现一些功能, 如用在 template 模板中调用这些方法.
- class Teacher(models.Model):
- ......
- def __str__(self): # Python2:__unicode__
- return f'Teacher : {self.nickname}'
- def get_course_num(self):
- """获取课程数"""
- return self.Course_set.all().count()
- class Course(models.Model):
- """课程信息表"""
- teacher = models.ForeignKey(Teacher, null=True, blank=True, on_delete=models.CASCADE,
- verbose_name="课程讲师") # 删除级联
- View Code
. 在 html 模板中调用此函数 {{ teacher.get_course_num }}
2 对于一些字段 里面采用 choice 来规定存储值范围的的调用, 如:
degree = models.CharField(max_length=7, choices=(('primary', '初级'), ('midd', '中级'), ('high', '高级')), verbose_name='课程难度')
数据库中的值限定在 ('primary', 'midd', 'high') 之中, 我们希望显示为 ( '初级', '中级', '高级' ) 可以采用 {{ course.get_degree_display }}
4 利用 modle 对数据库进行操作:
- from django.db.models import Count, Avg, Max, Min, Sum, F, Q
- from django.views.generic import View
- class IndexView(View):
- """主页"""
- def get(self, request):
- # # 1. 查询, 检索, 过滤
- # teachers = Teacher.objects.all()
- # print(teachers)
- # teacher2 = Teacher.objects.get(nickname='Jack') # get() 只能返回一条结果, 多条则会报错
- # print(teacher2, type(teacher2))
- # teacher3 = Teacher.objects.filter(fans__gte=500) # QuerySet, 可以是多条结果
- # for t in teacher3:
- # print(f"讲师姓名 {t.nickname}-- 粉丝数 {t.fans}")
- # # 2. 字段数据匹配, 大小写敏感
- # teacher4 = Teacher.objects.filter(fans__in=[666, 1231])
- # print(teacher4)
- # teacher5 = Teacher.objects.filter(nickname__icontains='A')
- # print(teacher5)
- # # 3. 结果切片, 排序, 链式查询
- # print(Teacher.objects.all()[:1])
- # teacher6 = Teacher.objects.all().order_by('-fans')
- # for t in teacher6:
- # print(t.fans)
- # print(Teacher.objects.filter(fans__gte=500).order_by('nickname'))
- # # 4. 查看执行的原生 SQL
- # print(str(Teacher.objects.filter(fans__gte=500).order_by('nickname').query))
- # 结果为:
- """SELECT `courses_teacher`.`nickname`, `courses_teacher`.`introduction`, `courses_teacher`.`fans`,
- `courses_teacher`.`created_at`, `courses_teacher`.`updated_at` FROM `courses_teacher`
- WHERE `courses_teacher`.`fans`>= 500 ORDER BY `courses_teacher`.`nickname` ASC
- """""" 返回新 QuerySet API"""
- # 1.all(), filter(), order_by(), exclude(), reverse(), distinct()
- # s1 = Student.objects.all().exclude(nickname='A 同学')
- # for s in s1:
- # print(s.nickname, s.age)
- # s2 = Student.objects.all().exclude(nickname='A 同学').reverse()
- # for s in s2:
- # print(s.nickname, s.age)
- # 2.extra(), defer(), only() 实现字段别名, 排除一些字段, 选择一些字段
- # s3 = Student.objects.all().extra(select={"name": "nickname"})
- # for s in s3:
- # print(s.name)
- # print(str(Student.objects.all().only('nickname', 'age').query))
- # 3.values(), values_list() 获取字典或元组形式的 QuerySet
- # print(TeacherAssistant.objects.values('nickname', 'hobby'))
- # print(TeacherAssistant.objects.values_list('nickname', 'hobby'))
- # print(TeacherAssistant.objects.values_list('nickname', flat=True))
- # 4.dates(), datetimes() 根据时间日期获取查询集
- # print(Course.objects.dates('created_at', 'year', order='DESC'))
- # print(Course.objects.datetimes('created_at', 'year', order='DESC'))
- # 5.union(), intersection(), difference() 并集, 交集, 差集
- # p_240 = Course.objects.filter(price__gte=240)
- # p_260 = Course.objects.filter(price__lte=260)
- # print(p_240.union(p_260))
- # print(p_240.intersection(p_260))
- # print(p_240.difference(p_260))
- # 6.select_related() 一对一, 多对一查询优化, prefetch_related() 一对多, 多对多查询优化; 反向查询
- # courses = Course.objects.all().select_related('teacher')
- # for c in courses:
- # print(f"{c.title}--{c.teacher.nickname}--{c.teacher.fans}")
- # students = Student.objects.filter(age__lt=30).prefetch_related('course')
- # for s in students:
- # print(s.course.all())
- # print(Teacher.objects.get(nickname="Jack").course_set.all())
- # 7.annotate() 使用聚合计数, 求和, 平均数 raw() 执行原生的 SQL
- # print(Course.objects.values('teacher').annotate(vol=Sum('volume')))
- # print(Course.objects.values('teacher').annotate(pri=Avg('price')))
- # """不返回 Query API"""
- # # 1. 获取对象 get(), get_or_create(), first(), last(), latest(), earliest(), in_bulk()
- # print(Course.objects.first())
- # print(Course.objects.last())
- # print(Course.objects.earliest())
- # print(Course.objects.latest())
- # print(Course.objects.in_bulk(['Python 系列教程 4', 'Golang 系列教程 1']))
- #
- # # 2. 创建对象 create(), bulk_create(), update_or_create() 创建, 批量创建, 创建或更新
- #
- # # 3. 更新对象 update(), update_or_create() 更新, 更新或创建
- # Course.objects.filter(title='Java 系列教程 2').update(price=300)
- #
- # # 4. 删除对象 delete() 使用 filter 过滤
- # Course.objects.filter(title='test').delete()
- #
- # # 5. 其它操作 exists(), count(), aggregate() 判断是否存在, 统计个数, 聚合
- # print(Course.objects.filter(title='test').exists())
- # print(Course.objects.filter(title='Java 系列教程 2').exists())
- # print(Course.objects.count())
- # print(Course.objects.aggregate(Max('price'), Min('price'), Avg('price'), Sum('volume')))
- # courses = Course.objects.values('teacher').annotate(t=GroupConcat('title', distinct=True,
- # ordering='title ASC',
- # separator='-'))
- # for c in courses:
- # print(c)
- # Course.objects.update(price=F('price') - 11)
- print(Course.objects.filter(volume__lte=F('price') * 10))
- print(Course.objects.filter(Q(title__icontains='java') & Q(volume__gte=5000)))
- print(Course.objects.filter(Q(title__icontains='golang') | Q(volume__lte=1000)))
- View Code
5 django 的 modle 不经可以在 django view 这些地方操作, 也可以调用此 modle 对数据库进行操作, 如不用写 sql 语句而使用相关 modle 类 对数据库数据实现导入导出修改查找等操作 (即 ORM),
- import os
- import sys
- import random
- import django
- from datetime import date
- project_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- sys.path.append(project_path) # 将项目路径添加到系统搜寻路径当中
- os.environ['DJANGO_SETTINGS_MODULE'] = 'imooc.settings' # 设置项目的配置文件
- django.setup()
- from courses.models import Teacher, Course, Student, TeacherAssistant
- def import_data():
- """使用 Django ORM 导入数据"""
- # 讲师数据 create()
- Teacher.objects.create(nickname="Jack", introduction="Python 工程师", fans=666)
- # 课程数据 bulk_create()
- Course.objects.bulk_create([Course(title=f"Python 系列教程 {i}", teacher=Teacher.objects.get(nickname="Jack"),
- type=random.choice((0, 1, 2)),
- price=random.randint(200, 300), volume=random.randint(100, 10000),
- online=date(2018, 10, 1))
- for i in range(1, 5)])
- # 学生数据 update_or_create()
- Student.objects.update_or_create(nickname="A 同学", defaults={"age": random.randint(18, 58),
- "gender": random.choice((0, 1, 2)),
- "study_time": random.randint(9, 999)})
- # 正向添加
- # 销量大于等于 1000 的课程
- Student.objects.get(nickname="A 同学").course.add(*Course.objects.filter(volume__gte=1000))
- # 反向添加
- # 学习时间大于等于 500 小时的同学
- Course.objects.get(title="Python 系列教程 1").student_set.add(*Student.objects.filter(study_time__gte=500))
- # 助教数据 get_or_create()
- TeacherAssistant.objects.get_or_create(nickname="助教 1", defaults={"hobby": "慕课网学习", "teacher":
- Teacher.objects.get(nickname="Jack")})
- return True
- if __name__ == "__main__":
- if import_data():
- print("数据导入成功!")
- View Code
注: 导入 modle 类必须在 django.setup() 之后导入, 否则找不到路径
注: 主要参考 慕课网课程 全面掌握 Django ORM https://www.imooc.com/learn/1087
来源: http://www.bubuko.com/infodetail-2976972.html