django orm 基本

2019-03-06 07:17:56来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

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

 


原文链接:https://www.cnblogs.com/cdcc1/p/10478774.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:python shell与反弹shell

下一篇:记录python之递归函数