django与数据库的运用

前言

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

推荐阅读更多精彩内容