零基础入手Django(七):模型基础2

今天,小叮当来为大家继续分享Django干货~

主要内容有:常用的查询、常用字段类型及常用参数、表关系的实现

一、常用的查询

  • 常用的查询方法总结

  • #1.获取所有记录
    rs = User.objects.all()
    #2.获取第一条数据
    rs = User.objects.first()
    #3.获取最后一条数据
    rs = User.objecsts.last()
    #4.根据参数提供的条件获取过滤后的记录
    rs = User.objects.filter(name='xiaodingdang')
    #filter(**kwargs)方法:根据参数提供的提取条件,获取一个过滤后的QuerySet。
    #5.排除name等于xiaodingdang的记录
    rs = User.objects.exclude(name='xiaodingdang')
    #6.获取一个记录对象
    rs = User.objects.get(name= 'xiaodingdang')
    #get返回的对象具有唯一性质,如果符合条件的对象有多个,则get报错!
    #7.对结果排序order_by
    rs = User.objects.order_by('age')
    #8.多项排序
    rs = User.objects.order_by('age','id')
    #9.逆向排序 (在条件的前面加个负号)
    rs = User.objects.order_by('-age')
    #10.将返回来的QuerySet中的Model转换为字典
    rs = User.objects.all().values()
    #11.获取当前查询到的数据总数
    rs = User.objects.count()

    由于其使用方法在零基础入手Django(六):模型基础1中已经为大家介绍过,这里只挑选出来几个具有代表性的进行演示。

    (1)使用order_by逆向排序

    重新定义查询视图函数

    #查询数据
    def search_user(request):
        rs = User.objects.all()
        print('我是默认查询结果',rs)
        order_rs = User.objects.order_by('-age')
        print('我是倒序查找',order_rs)
        return HttpResponse('我在使用order_by方法查询')

    在浏览器中访问

    在Pycharm后台端,查看输出结果

    可以看到,默认查询是按id正序排列。使用order_by方法后,我们成功使得输出按照age进行了逆向排列。

    值得注意,在按age倒序输出时,相同age的数据还是按id从小到大排列了,例如age=18时,先输出了id=1的xdd才输出了id=2的小叮当。

    这时我们就可以使用order_by,对多个字段进行排序,使得当age相同时,便按id从大到小进行排序。

    在视图函数中添加如下语句:

    ors = User.objects.order_by('-age','-id')
    print('我使用了多字段',ors)

    在浏览器中访问后,在后台查看

    (2)values将输出结果字典化

    重新定义查询视图函数

    #查询数据
    def search_user(request):
        rs = User.objects.all()
        print('我是默认查询结果',rs)
        vrs = User.objects.all().values()
        print('我是字典化后的结果',vrs)   
        return HttpResponse('我在使用values字典化查询结果')

    在浏览器中查看

    在pycharm后台端查看输出结果

    (3)count查询数据总数

    在查询视图函数中,添加如下代码

    num = User.objects.count()
    print('数据总数为',num)

    在浏览器中查看

    在pycharm后台端查看结果

    2.常用的查询条件总结

    #1.等于号  exact
    rs = User.objects.filter(name__exact='xiaodingdang')
    #iexact是忽略了大小写匹配的等于

    #2.包含  contains
    rs = User.objects.filter(name__contains='xiao')
    #icontains是忽略了大小写匹配的包含

    #3.以什么开始  startswith
    rs = User.objecsts.filter(name__startswith='xiao')
    #istartswith是忽略了大小写的startswith

    #4.以什么结尾  endswith
    rs = User.objects.filter(name__endswith='dang')
    #iendswith是忽略了大小写的endswith

    #5.成员所属 in
    rs = User.objects.filter(age__in=[18,19,20])

    #6.大于 gt
    rs = User.objects.filter(age__gt=18)

    #7.大于等于 gte
    rs = User.objects.filter(age__gte=18)

    #8.小于 lt
    rs = User.objects.filter(age__lt=20)

    #9.小于等于 lte
    rs = User.objects.filter(age__lte=20)

    #10.区间 range
    rs = User.objects.filter(age__range=(18,20))

    #11.判断是否为空
    rs = User.objects.filter(city__isnull=True)

    定义查询视图函数

    #查询数据
    def search_user(request):
        ers = User.objects.filter(name__exact='小叮当')
        print('查询name等于小叮当的数据',ers)
        crs = User.objects.filter(name__contains='x')
        print('查询name包含了x的数据',crs)
        srs = User.objects.filter(name__startswith='神仙')
        print('查询name以神仙开头的数据',srs)
        endrs = User.objects.filter(name__endswith='叮当')
        print('查询name以叮当结尾的数据',endrs)
        grs = User.objects.filter(age__gt=19)
        print('查询age大于19的数据',grs)
        lrs = User.objects.filter(age__lt=19)
        print('查询age小于19的数据',lrs)
        rrs = User.objects.filter(age__range=(18,19))
        print('查询age在[18,19)的数据',rrs)
        irs = User.objects.filter(age__in=[18,19])
        print('查询age为18和19的数据',irs)
        nrs =User.objects.filter(city__isnull=True)
        print('判断city字段是否为空',nrs)
        return HttpResponse('我在使用条件查询数据')

    在浏览器中访问

    在后台查看结果

    其中值得注意的是,在django中使用条件查询时,相当于使用了sql语句中的where。其语法是:字段名__规则 (字段名和规则之间是两条下划线

    例如:

    nrs =User.objects.filter(city__isnull=True)

    就相当于sql语句

    select * from .... where city is null

    二、常用字段类型及常用参数

  • 常用的字段类型映射关系

  • 在models.py中我们可以看到,我们只使用了AutoField(自增长类型)、CharField(字符类型)、IntegerField(整数类型)等数据类型。

    其实,在Django中还有其它几种常用的字段类型,它们的映射关系如下

    常用的字段类型总结如下

    1.IntegerField:整型,映射到数据库中的int类型。

    2.CharField:字符类型,映射到数据库中的varchar类型,通过max_length指定最大长度。

    3.TextField:文本类型,映射到数据库中的text类型。

    4.BooleanField:布尔类型,
    映射到数据库中的tinyint类型,在使用的时候
    传递True/False进去。如果要可以为空,则用NullBooleanField。

    5.DateField:日期类型,没有时间。
    映射到数据库中是date类型。在使用的时候,
    可以设置DateField.auto_now每次保存对象时,自动设置该字段为当前时间。
    设置DateField.auto_now_add当对象第一次被创建时自动设置当前时间。

    6.DateTimeField:日期时间类型,
    映射到数据库中的是datetime类型。
    在使用的时候,传递datetime.datetime()进去。

    Field的常用参数总结如下:

    1.primary_key:指定是否为主键。
    2.unique:指定是否唯一。
    3.null:指定是否为空,默认为False。
    4.blank:等于True时form表单验证时可以为空,默认为False。
    5.default:设置默认值。
    6.DateField.auto_now:每次修改都会将当前时间更新进去,只有调用
    QuerySet.update方法将不会更新,这个参数只是Date和DateTime以及
    TimModel.save()方法才会调用e类才有的。
    DateField.auto_now_add:第一次添加进去,都会将当前时间设置进去,
    以后修改,不会修改这个值。

    2.使用常用类型创建数据表

    (1)我们在models.py中建Field_Test模型类作为一张新的表

    class Field_Test(models.Model):     name = models.CharField(max_length=30,unique=True)
    age = models.IntegerField()
    note = models.TextField()
    gender = models.BooleanField(default=True)
    create_time = models.DateField(auto_now_add=True)#第一次存入数据的时间     update_time = models.DateTimeField(auto_now=True)#每次更新就会修改

    (2)在pycharm的tools中找到"Run manage.py Task..."

    执行makemigrations model_test

    (3)执行migrate model_test

    (4)使用xshell进行查看

    执行命令“mysql -u xdd(用户名) -p(输入密码)”

    执行命令“use mydb;"

    执行命令”show tables;

    执行命令”desc model_test_field_test;"

    3.向表中插入数据

    (1)重新定义添加数据的视图函数

    from .models import Field_Test
    def add_user(request):
      Field_Test.objects.create(name='小叮当',age=17,
    note='我是小叮当',gender=False)
      return HttpResponse('小叮当在向field_test中添加数据!')

    (2)在浏览器中访问

    (3)通过xshell进行查看

    4.更新数据

    (1)重新定义添加数据的视图函数

    def add_user(request):
      rs = Field_Test.objects.get(id=1)
      rs.name = "快乐小叮当"
      rs.save()
      return HttpResponse('小叮当在更新数据!')

    (2)在浏览器中访问

    (3)通过xshell查看

    可以看到,数据更新的时间已经自动更新。但是显示的更新的时间与我们真实的时间相差了8个小时~大家知道这是时区默认设置导致的即可。

    值得注意,只有使用.save()方法更新数据,系统才会自动更新时间。而使用update方法更新,则不会调用auto_now自动更新时间。

    三、表关系的实现

    1.表关系示意图

    2.示例

    为了明确在django中如何创建丰富的表关系,小叮当为大家示例如下

    (1)表关系图

    假如有下面这几张表

    它们的关系可以这样表示:

    (2)在项目中新建app,并注册

    在项目中新建名为db_test的app用来实现表关系。在Tools中打开Run manage.py Task...

    执行命令“startapp db_test"

    在项目处,右键将创建好的app下载下来

    在项目的settings文件中注册创建好的app

    (3)创建表

    我们在建好的”db_test“的models.py中创建表。值得注意,当出现一对多,多对多,一对一等复杂关系时,我们一般先从”一“这一端来创建表。

    在models.py中创建模型类如下:

    #1.创建学院信息表
    class Department(models.Model):
          d_id = models.AutoField(primary_key=True)
          d_name = models.CharField(max_length=30)


    #2.创建学生信息表
    class Student(models.Model):
        s_id = models.AutoField(primary_key=True)
        s_name = models.CharField(max_length=30)
        #实现一对多关系ForeignKey 其中on_delete为必填字段使用级联删除CASCADE
        department = models.ForeignKey('Department',on_delete=models.CASCADE)

    #3.课程信息表
    class Course(models.Model):
        c_id = models.AutoField(primary_key=True)
        c_name = models.CharField(max_length=30)
        #实现多对多关系 ManyToManyField
        student = models.ManyToManyField('Student')


    #4.学生详细信息表
    class Stu_detail(models.Model):
        # 实现一对一关系OneToOneField 其中on_delete为必填字段使用级联删除CASCADE
          student = models.OneToOneField('Student',on_delete=models.CASCADE)
          age = models.IntegerField()
          gender = models.BooleanField(default=1)
          city = models.CharField(max_length=30,null=True)

    在Pycharm的Tools中打开Run manage.py Task...

    执行 makemigrations

    执行 migrate

    在xshell 的mysql中 执行 show tables;

    执行 desc db_test_department; 查看学院信息表

    执行 desc db_test_student;  查看学生信息表

    可以看到,学生信息表中自动为我们关联生成了”department_id"外键,也就是department表的d_id

    关于级联删除:

    只有引用的数据全部删除后,才可以删除被引用表中的父类数据。例如,学院信息表中1代表计算机学院。在学生信息表中,小明、小红、小花都是计算机学院,他们的外键值都是1,想要在学院信息表中删除计算机学院,需要在学生信息表中先删除了引用计算机学院的小明、 小红、小花。

    执行 desc db_test_course; 查看课程表

    执行 desc db_test_stu_detail; 查看学生详细信息表

    可以看到,已经按照我们的设置,学生详细信息表和学生表建立了一对一的关系。

    再次执行,show tables;

    我们看到,我们已实现了学生表与课程表的多对多关系,系统已为我们自动生成了中间信息表“db_test_course_student"。

    执行 desc db_test_course_student; 进行查看,结果如下

    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 210,978评论 6 490
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 89,954评论 2 384
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 156,623评论 0 345
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 56,324评论 1 282
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 65,390评论 5 384
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 49,741评论 1 289
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 38,892评论 3 405
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 37,655评论 0 266
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 44,104评论 1 303
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 36,451评论 2 325
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 38,569评论 1 340
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 34,254评论 4 328
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 39,834评论 3 312
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 30,725评论 0 21
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 31,950评论 1 264
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 46,260评论 2 360
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 43,446评论 2 348

    推荐阅读更多精彩内容