美文网首页
django与数据库的运用

django与数据库的运用

作者: 遥远的她197 | 来源:发表于2019-03-19 20:59 被阅读0次

    前言

    通过讲mysql的系统,翻译一遍,在django中通过创建model去和数据库中的表进行一一映射,并且通过ORM封装 的处理方式去练习这一道习题,并写出如下的解题答案

    1.数据库准备

    在model中定义数据库,其中的性别,男的存1,女的存0。

    class Student(models.Model):
        stuname = models.CharField(max_length=20)
        stusex = models.BooleanField()
        stubirth = models.DateField()
        stutel = models.CharField(max_length=255)
    
        class Meta:
            db_table = 'student'
    
    

    2.数据库迁移

    python manage.py makemigrations
    python manage.py migrate
    
    

    3. 数据插入

    3.1 使用表单form提交post请求数据
    <form action="/app/addStu/" method="post">
        stuname: <input type="text" name="name">
        stusex: <input type="text" name="sex">
        stubirth: <input type="date" name="birth">
        stutel: <input type="text" name="tel">
        <input type="submit" value="提交">
    </form>
    
    
    3.2 获取post请求,获取请求数据,并且创建数据
    方法1:获取类对象进行save()保存
    stu = Student()
    stu.stuname = stuname
    stu.stusex = sex
    stu.stubirth = birth
    stu.stutel = tel
    stu.save()
    
    
    方法2:使用create()方法
    Student.objects.create(stuname=stuname, 
                            stusex=sex,
                            stubirth=birth, 
                            stutel=tel)
    
    
    方法3:使用初始化
    在Student模型中重构__init__()方法,添加如下代码
    
    def __init__(self, name, birth=None, sex=None,tel=None):
        super().__init__()
        self.stuname = name
        self.stubirth = birth 
        self.stusex = sex
        self.stutel = tel
    
    # 视图函数中定义创建学习信息的方法为:
    stu = Student('小草', 18, 1, 12331244323)
    stu.save()
    
    

    注意:重构init方法的时候,一定要使用super().init(),否则会报studen对象没有_state的属性。

    4. 查询所有的学生信息

    使用all()方法获取所有的数据

    Student.objects.all()
    
    

    4. 查询所有女学生的姓名和出生日期

    Student.objects.filter(stusex=0)
    或者
    Student.objects.exclude(stusex=1)
    
    

    其中:

    filter():返回符合条件的数据

    exclude():过滤掉符合条件的数据

    5.查询所有的学生,按照id从大到小排序

    Student.objects.all().order_by('-id')
    
    

    其中:

    order_by('id'):表示按照id升序的排列

    order_by('-id'):表示按照id降序的排列

    6. 查询所有的学生信息,并序列化

    Student.objects.all().values()
    Student.objects.all().values('s_name', 's_age')
    
    

    7.查询所有80后学生的姓名、性别和出生日期(筛选)

    Student.objects.filter(stubirth__gte='1980-01-01', 
                            stubirth__lte='1990-01-01')
    
    

    8.查询名字中有王字的学生的姓名(模糊),like '%小%', like '小%',like '%小'

    Student.objects.filter(s_name__contains='小')
    Student.objects.filter(s_name__startswith='小')
    Student.objects.filter(s_name__endswith='小')
    
    

    9.查询id等于1,2的学生信息

    # select * from student where id in (1,2)
    stus = Student.objects.filter(id__in=[1,2])
    
    

    10. 获取id为1的信息,get()和filter()的使用

    Student.objects.filter(id=1)
    Student.objects.get(id=1)
    Student.objects.get(pk=1)
    
    # get获取不到数据会直接报错, filter获取不到数据是返回空
    stus = Student.objects.get(pk=5)
    Student.objects.filter(id=5)
    
    # get只能返回一个数据,返回多个会报错
    Student.objects.get(s_age=15) # 前提条件:数据库中s_age为15的数据有多条
    
    

    11.获取所有学生(按照id降序)中第一个/最后一个学生信息

    # 获取按照id降序的第一个学生信息
    Student.objects.all().order_by('-id')[0]
    Student.objects.all().order_by('-id').first()
    # 获取所有学生(按照id降序)中最后一个学生信息
    Student.objects.all().order_by('-id').last()
    

    ===========模型加参===========

    1.建表

    class Grade(models.Model):
        g_name = models.CharField(max_length=10, unique=True, null=False)
    
        class Meta:
            db_table = 'grade'
    
    
    class StudentInfo(models.Model):
        address = models.CharField(max_length=50, null=True)
        phone = models.CharField(max_length=11, null=True)
    
        class Meta:
            db_table = 'stu_info'
    
    
    class Student(models.Model):
        # 长度为10,且唯一不能为空的姓名s_name字段  CharField - 字符串类型
        s_name = models.CharField(max_length=10, unique=True, null=False)
        # IntegerField - 整型字段
        age = models.IntegerField(default=18)
        # auto_now_add:表示第一次创建数据时,自动默认为创建的时间
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now: 表示修改时,自动更新为修改时间
        operate_time = models.DateTimeField(auto_now=True)
        # 是否删除
        is_delete = models.BooleanField(default=0)
        # 定义浮点数总长度3位,小数点后1位(decimal_places=1)
        yuwen = models.DecimalField(max_digits=3, decimal_places=1, null=True)
        math = models.DecimalField(max_digits=3, decimal_places=1, null=True)
        # 一对一:定义在关联的两个模型中的任何一方都可以
        stuinfo = models.OneToOneField(StudentInfo, related_name='stu', on_delete=models.CASCADE, null=True)
        # 一对多:只能定义在‘多’的一方
        grade = models.ForeignKey(Grade, related_name='stu', on_delete=models.CASCADE, null=True)
    
        class Meta:
            db_table = 'student'
    

    2.数据库迁移

    python manage.py makemigrations
    python manage.py migrate
    
    模型对应关系描述如下:

    1:1 一对一 OneToOneField
    1:N 一对多 ForeignKey
    M:N 多对多 ManyToManyField 会自动建一个中间表

    在views.py文件中
    def add_stu_info(request):
        if request.method == 'GET':
            # 向拓展表中添加信息
            stu_info = StudentInfo()
            stu_info.phone = '13545455433'
            stu_info.save()
            s_id = stu_info.id
            stu = Student.objects.filter(s_name='小明').first()
            # 第一种写法: 学生对象.OneToOneField字段 = 关联对象
            stu.stuinfo = stu_info
            # 第二种写法: 学生对象.OneToOneField字段 = 关联对象.id
            stu.stuinfo_id = stu_info.id
            stu.save()
    
            return HttpResponse('添加拓展表信息')
    
    
    def sel_stuinfo_by_stu(request):
        if request.method == 'GET':
            # 通过学生信息找拓展表信息
            stu = Student.objects.get(s_name='小明')
            # StudentInfo.objects.get(pk=stu.stuinfo_id) 等价于stu.stuinfo
            # 学生对象(stu).OneToOneField字段(stuinfo)
            stu.stuinfo
            return HttpResponse('获取拓展表信息成功')
    
    
    def sel_stu_by_info(request):
        if request.method == 'GET':
            # 通过拓展表中的手机号码找学生信息
            stuinfo = StudentInfo.objects.filter(phone='13545455433').first()
            # stu = Student.objects.filter(stuinfo=stuinfo)
            # stu = Student.objects.filter(stuinfo_id=stuinfo.id)  # 和上面一样
            # print(stu)
            # 拓展表对象.关联的模型名称小写
            # stu = stuinfo.student  # 和上面两步一样,这步很简单
            # 定义related_name参数, 拓展表对象.related_name值
            stu = stuinfo.stu  # 这的stu是onetonoe字段的related_name参数,它和上面那步是互斥的
            print(stu)
            return HttpResponse('通过拓展表信息查询学生表信息')
    
    
    def add_grade(request):
        if request.method == 'GET':
            # 添加班级信息, 并给学生分配班级
            names = ['Python班级', 'Java班级', 'Php班级', 'C++班级']
            for name in names:
                if Grade.objects.filter(g_name=name).exists():
                    Grade.objects.creat(g_name=name)
            # 分配班级
            stus = Student.objects.filter(pk_in=[5, 6, 7, 10, 11, 12]).all()
            g = Grade.objects.filter(g_name='Python班级').first()
            for stu in stus:
                stu.grade = g
                # stu.grade_id = g.id
                stu.save()
            return HttpResponse('添加班级和学生信息')
    
    
    def sel_grade_by_stu(request):
        if request.method == 'GET':
            # 通过学生查询班级信息
            stu = Student.objects.filter(s_name='小明').first()
            g = stu.grade
            print(g)
            # 班级查询学生
            stus = g.student_set.all()  # 和下面一样
            stus = g.stu.all()  # 定义了related_name='stu',
    但是用了related_name之后,就不能用_set了
    
            return HttpResponse('通过学生查询班级成功')
    

    多对多

    先声明两个类Course, Student

    class Course(models.Model):
        c_name = models.CharField(max_length=10, unique=True, null=False)
    
        class Meta:
            # 指定表名
            db_table = 'course'
    
    class Student(models.Model):
        # 长度为10,且唯一不能为空的姓名s_name字段  CharField - 字符串类型
        s_name = models.CharField(max_length=10, unique=True, null=False)
        # IntegerField - 整型字段
        age = models.IntegerField(default=18)
        # auto_now_add:表示第一次创建数据时,自动默认为创建的时间
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now: 表示修改时,自动更新为修改时间
        operate_time = models.DateTimeField(auto_now=True)
        # 是否删除
        is_delete = models.BooleanField(default=0)
        # 定义浮点数总长度3位,小数点后1位(decimal_places=1)
        yuwen = models.DecimalField(max_digits=3, decimal_places=1, null=True)
        math = models.DecimalField(max_digits=3, decimal_places=1, null=True)
    
        # 多对多
        course = models.ManyToManyField(Course, related_name='stu')
    
        class Meta:
            db_table = 'student'
    

    views.py文件中

    def add_course(request):
        if request.method == 'GET':
            # 添加课程信息
            names = ['大学语文', '日语', '数电', '模电']
            for name in names:
                cou = Course()
                cou.c_name = name
                cou.save()
    
            return HttpResponse('添加课程成功')
    
    
    def sel_cou_by_stu(request):
        if request.method == 'GET':
            # 查询id为1的学生所选择的课程信息
            stu = Student.objects.get(pk=1)
            # 学生查找课程
            stu.course
    
            # 课程查询学生
            cou = Course.objexts.get(pk=1)
            cou.student_set.all()  # student是小写的类名, 没有related_name之前可以用
            cou.stu.all()
            return HttpResponse('多对多的查询成功')
    
    
    def add_del_stu_cou(request):
        if request.method == 'GET':
            # 增删中间表的信息
            # 给小王分配'日语', '数电', '模电'
            stu = Student.objects.filter(s_name='小明').first()
            cou1 = Course.objects.get(c_name='日语')
            cou2 = Course.objects.get(c_name='数电')
            cou3 = Course.objects.get(c_name='模电')
            # 新增中间表数据
            stu.course.add(cou1)
            stu.course.add(cou2)
            stu.course.add(cou3)  # add方法加入课程(flask中用的append), 此时中间表就有信息了
            # cou1.stu.add(学生对象)  # 和上面一样的
    
            # 删除中间表数据  stu.course此时有3门课程
            stu.course.remove(cou2)
            stu.course.remove(cou3)  # 此时删掉了数电和模电课程
            return HttpResponse('操作中间表信息成功')
    
    
    def on_delete_stu(request):
        if request.method == 'GET':
            # 演示删除, on_delete参数的效果
            stuinfo = StudentInfo.objects.get(id=6)
            stuinfo.delete()
            # models.CASCADE 表示:主键所在行的数据被删, 外键所在行的数据也会被删
            # models.PROTECT 表示:主键有对应的外键数据时, 不让删除主键的数据
            # models.SET_NULL 表示:主键删除, 外键置空
            # 常用的就上面三个
            return HttpResponse('on_delete演示成功')
    

    模型关联关系

    一对一

    class A():
        id = modules.IntegerFiled()
    
    class B():
        aa = mldels.OneToOneField(A,, on_delete=models.CASCADE, null=True,related_name='cc')
    
    • OneToOneField(关联模型)
    • 模型定义
      • 关联名 = models.OneToOneField(关联的表名, related_name = '关系名', on_delete=models.CASCADE, null=True)
    • 已知 A 对象 a 查询 B 对象
      • 当 related_name 没定义时: a.b
      • 当 related_name = 'cc'时: a.cc
    • 已知 B 对象 b 查询 A 对象 b.aa
    • 一对一:定义在关联的两个模型中的任意一方都可以

    一对多

    class A():
        id
    
    class B():
        aa = models.ForeignKey(A, on_delete=models.CASCADE, null=True,related_name='cc')
    
    • ForeignKey(关联模型)
    • 模型定义
      • aa = ForeignKey(A)
    • 已知 A 对象 a,查询 B 对象
      • 当 related_name 没定义时: a.b_set
      • 当 related_name = 'cc'时: a.cc
    • 已知 B 对象 b 查询 A 对象 b.aa
    • 一对多:定义在'多'的一方

    多对多

    • course = models.ManyToManyField(Course 要进行关联的表的名字,related_name='stu') 会自动生成中间文件,中间文件的表名为 course
    • 查询 id 为 1 的学生课程信息
    • stu = Student.objects.get(pk=1)
    • 学生查询课程
      • stu.course
    • 课程查询学生
      • cou = Course.objects(pk=1)
      • 当 related_name 没定义时: cou.student_set.all()
      • 当 related_name 定义时: cou.stu.all()
    • 增加中间表信息
      • stu = Student.objects.filter(s_name = '小明').first()
      • cou1 = Course.objects.get(c_name='日语')
      • stu.course.add(cou1)
    • 删除中间表信息
      • stu.course.remove(cou1)
    • on_delete 参数
      • models.CASCADE 表示: 主键所在行的数据被删,外键所在行的数据也会被删
      • models.PROTECT 表示: 主键有对应的外键数据时,不让删除主键的数据
      • models.SET_NULL 表示: 主键删除,外键置空
    • 注意: ManyToManyFiled 定义的字段定义在任何一个关联模型中都可以

    相关文章

      网友评论

          本文标题:django与数据库的运用

          本文链接:https://www.haomeiwen.com/subject/yocomqtx.html