Django模型进阶(Mysql配置、模型管理,表关联、一对一、一对多,多对多)

news2024/9/24 6:31:52

模型进阶:

Mysql配置:

1.安装mysql

2安装MySQL驱动,使⽤mysqlclient

pip install mysqlclient

pip install -i https://pypi.douban.com/simple mysqlclient
Linux Ubuntu下需要先安装:apt install libmysqld-dev
再安装: apt install libmysqld-dev

在这里插入图片描述

3.在Django中配置和使⽤mysql数据库

使⽤mysql数据库,settings中配置如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', 
'NAME': 'mydb',
'USER': 'root', 'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}

在这里插入图片描述

在这里插入图片描述

迁移到mysql中。

在这里插入图片描述

查看:

在这里插入图片描述

mysql和sqlite只有配置是不一样的,其他的语句是类似的。

管理关系:

多个模块关联关联分类

  • ·ForeignKey:⼀对多,将字段定义在多的端中,外键
  • ·ManyToManyField:多对多,将字段定义在两端的任意⼀端中
  • ·OneToOneField:⼀对⼀,将字段定义在任意⼀端中

⼀对多关系,举例说明:
⼀个班级可以有多个学⽣, ⼀个学⽣只能属于⼀个班级

多对多就是两个一对多。


class Grade(models.Model):
	name = models.CharField(max_length=20) 
class Student(models.Model):
    name = models.CharField(max_length=20)
    grade = models.ForeignKey(Grade, on_delete=)
对象的使⽤:
    正向(在Student这边,有grade属性的这⼀边): 获取学⽣所在班级(对象): stu.grade
   		获取学⽣所在班级的属性: stu.grade.name
    反向(在Grade这边):
        获取班级的所有学⽣(获取Manager对象):grade.student_set
        获取班级的所有学⽣(获取QuerySet查询集): grade.student_set.all()

filter(),get()等操作中的使⽤:
正向(在Student这边,有grade属性的这⼀边):
Student.objects.filter(属性 name='1')
如:Student.objects.filter(grade name='1') 反向(在Grade这边):
Grade.objects.filter(类名⼩写 id=7)
如:Grade.objects.filter(student id=7)

连表结构:

⼀对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
⼀对⼀:models.OneToOneField(其他表) 应⽤场景:
⼀对多:当⼀张表中创建⼀⾏数据时,有⼀个单选的下拉框(可以被重复选择)
例如:创建⽤户信息时候,需要选择⼀个⽤户类型【普通⽤户】【⾦牌⽤户】【铂⾦⽤户】
多对多:在某表中创建⼀⾏数据时,有⼀个可以多选的下拉框。(猫眼App, 淘票票,格拉瓦电影) 例如:创建⽤户信息,需要为⽤户指定多个爱好。
⼀对⼀:在某表中创建⼀⾏数据时,有⼀个单选的下拉框(下拉框中的内容被⽤过⼀次就消失了)
例如:有个身份证表,有个person表。每个⼈只能有⼀张身份证,⼀张身份证也只能对应⼀个⼈,这就是⼀对⼀关系。
一对多:

在这里插入图片描述

在这里插入图片描述

项目工程下urls.py

from django.contrib import admin
from django.urls import path
from OnetoMany import views as one2many_view


urlpatterns = [

    # 1对多
    path('one2many/adduser/', one2many_view.add_user),
    path('one2many/deluser/', one2many_view.del_user),
    path('one2many/updateuser/', one2many_view.update_user),
    path('one2many/getuser/', one2many_view.get_user),



    path("admin/", admin.site.urls),
]

添加数据:

一对多下 的views.py 提供接口层。

from django.shortcuts import render, HttpResponse
from OnetoMany.models import *


# 一对多关系

# 添加数据
def add_user(request):
    # 给UserType添加数据
    # user_types = ['青铜', '白银', '黄金', '钻石', '大师', '王者']
    # for name in user_types:
    #     UserType.objects.create(name=name)

    # # 给User添加数据
    for i in range(11, 30):
        #     User.objects.create(name=f'张三-{i}', age=i,
        #                         user_type_id=i % 6 + 1)
        # user_type 需要填入的是对象,而不是id

        User.objects.create(name=f'李四-{i}', age=100 + i,
                            user_type=UserType.objects.get(pk=i % 6 + 1))  # 拿到映射后的结果

    return HttpResponse('添加成功!')

在这里插入图片描述

删除数据:

views.py

from django.shortcuts import render, HttpResponse
from OnetoMany.models import *
# 删除数据
def del_user(request):
    # 删除User数据
    # User.objects.filter(id=6).delete()

    # 删除UserType数据
    UserType.objects.filter(id=3).delete()

    return HttpResponse('删除成功!')

from django.db import models


# 1对多 = 1:N
# 用户类型 : 用户 = 1:N
#   一种用户类型:可以有多个用户
#   一个用户:只属于一个用户类型


# 用户类型
class UserType(models.Model):
    name = models.CharField(max_length=30)


# 一个用户类型可以有多个用户
# on_delete 删除外键对另一个外键的影响
# 用户
class User(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField(default=18)
    # 外键
    user_type = models.ForeignKey(UserType, on_delete=models.CASCADE)  # 级联删除
    # user_type = models.ForeignKey(UserType, on_delete=models.PROTECT)  # 保护模式 有关联的 则阻止删除
    # user_type = models.ForeignKey(UserType, on_delete=models.SET_NULL, null=True)  # 置空模式
    # user_type = models.ForeignKey(UserType, on_delete=models.SET_DEFAULT, default=1)  # 置默认值
    # user_type = models.ForeignKey(UserType, on_delete=models.DO_NOTHING)  # 报错FOREIGN KEY constraint failed

    # # related_name: 关联名称, 设置反向查找的名称,原本使用user_set改为users
    # user_type = models.ForeignKey(UserType, on_delete=models.PROTECT,
    #                               related_name='users',  # 建议使用
    #                               )

# on_delete参数主要有以下几个可选值:
#     models.CASCADE  默认值(Django1.11),表示级联删除,即删除UserType时,相关联的User也会被删除。
#     models.PROTECT	保护模式, 阻止级联删除。
#     models.SET_NULL	置空模式,设为null,null=True参数必须具备
#     models.SET_DEFAULT 置默认值 设为默认值,default参数必须具备
#     models.SET()	删除的时候重新动态指向一个实体访问对应元素,可传函数
#     models.DO_NOTHING   什么也不做。
# 注意: 修改on_delete参数之后需要重新同步数据库,如果使用

修改数据:

# 修改数据
def update_user(request):
    # 修改UserType
    # 没有级联操作 因为关联的是id字段 而不是值,所以修改值没有任何影响
    # UserType.objects.filter(id=1).update(name='钻石')

    # 修改User
    User.objects.filter(id=2).update(age=1000)

    return HttpResponse('修改成功!')

在这里插入图片描述

查询数据:

from django.db import models

# 用户类型
class UserType(models.Model):
    name = models.CharField(max_length=30)

# 一个用户类型可以有多个用户
# on_delete 删除外键对另一个外键的影响
# 用户
class User(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField(default=18)
    # 外键
    # # related_name: 关联名称, 设置反向查找的名称,原本使用user_set改为users
    user_type = models.ForeignKey(UserType, on_delete=models.PROTECT,
                                  related_name='users',  # 建议使用
                                  )


views.py

# 查询数据
def get_user(request):
    # 正向查询:从User表去查找UserType 因为设置了外键
    user = User.objects.get(id=2)
    # print(user.name, user.age, user.user_type, user.user_type_id)
    # print(user.user_type.name, user.user_type.id)  # User所属UserType的所有数据
    # 张三 - 12 1000 UserType object(1) 1
    # 青铜 1

    # 反向查询:
    utype = UserType.objects.get(pk=1)
    print(utype.id, utype.name)  # UserType自己的属性
    # 1 青铜

    # user_set: 内部自动会生成的属性,可以让你反向查询到所有User集合
    # print(type(utype.user_set))  # RelatedManager 关联的管理器对象
    # # <class 'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager'>
    # print(utype.user_set.all())  # 查询集 QuerySet
    # # <QuerySet [<User: User object (2)>, <User: User object (8)>, <User: User object (14)>, <User: User object (21)>, <User: User object (2
    # # 7)>, <User: User object (33)>]>

    # print('-' * 60)

    # 在filter中还可以这么用
    # 比如:查找用户类型名称为’白银‘的所有用户
    # 相当于关联的就是一个对象
    # users = User.objects.filter(user_type=UserType.objects.get(name='白银'))  # 传入UserType对象
    users = User.objects.filter(user_type_id=2)  # 传入user_type_id
    users = User.objects.filter(user_type__name='白银')  # 传入UserType对象的name属性作为条件
    print(users)
    print('-' * 60)
    #
    # # related_name:关联名称
    utype = UserType.objects.get(pk=1)
    # # print(utype.user_set.all())  # 报错,使用了related_name就不可以在使用带_set的属性
    print(utype.users.all())

    return HttpResponse('查询成功!')

多对多:

多对多关系
针对多对多关系django会⾃动创建第三张表。也可以通过through参数指定第三张表。

在这里插入图片描述

创建模型:

在这里插入图片描述

from django.db import models

# 电影
class Movie(models.Model):
    name = models.CharField(max_length=100)
    duration = models.IntegerField(default=90)

# 用户
class User(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField(default=18)
    # 多对多关系
    movies = models.ManyToManyField(Movie)

模型迁移到数据库:

在这里插入图片描述

在这里插入图片描述

urls.py

from django.contrib import admin
from django.urls import path
from OnetoMany import views as one2many_view
from Manytomany import  views as many2many_view

urlpatterns = [

    # 1对多
    path('one2many/adduser/', one2many_view.add_user),
    path('one2many/deluser/', one2many_view.del_user),
    path('one2many/updateuser/', one2many_view.update_user),
    path('one2many/getuser/', one2many_view.get_user),

    # many2many
    path('many2many/add/', many2many_view.add),
    path('many2many/delete/', many2many_view.delete),
    path('many2many/get/', many2many_view.get_user_movie),


    path("admin/", admin.site.urls),
]


删除数据:

# 删除数据
def delete(request):
    # 删除User
    # User.objects.filter(id=9).delete()

    # 删除Movie
    # Movie.objects.filter(id=9).delete()

    # 删除中间表
    user = User.objects.get(name='张三1')
    user.movies.filter(name='阿凡达3').delete()

    return HttpResponse('删除成功!')

查询操作:

# 查询数据
def get_user_movie(request):
    # 获取用户收藏的所有电影
    user = User.objects.get(id=1)
    print(user.movies.all())

    # 获取电影被哪些用户收藏了
    # 反向则需要使用 模型名称_set
    movie = Movie.objects.get(id=4)
    print(movie.user_set.all())

    return HttpResponse('查询成功')

⽤户和组是典型的多对多关系:
class Group(models.Model):
	name = models.CharField(max_length=20)
	def str (self): 
		return self.name

class User(models.Model):
	name = models.CharField(max_length=64)
	password = models.CharField(max_length=64) 
	groups = models.ManyToManyField(Group)
	def str (self):
		return self.name
操作:增:
先分别创建user和group, 再使⽤add关联
    u = User(name='aa', password='123') 
    u.save()
    g = Group(name='g5')
    g.save()
通过Manager对象使⽤add()⽅法
u.groups.add(g) 或	
g.user_set.add(u)

删:
和⼀对多类似,删除user或group会级联删除user_groups表中的关联数据改:
和⼀对多类似,只修改当前表查:
正向:
查询id=2的⽤户所在的所有组group
u = User.objects.get(id=2) u.groups.all()
反向:
查询id=1的组中包含的所有⽤户
g = Group.objects.get(id=1)
g.user_set.all()
一对一:

⼀对⼀不是数据库的⼀个连表操作,⽽是Django独有的⼀个连表操作。⼀对⼀关系相当于是特殊的⼀对多关系,只是相当于加了unique=True。
⼀个⼈只能有⼀张身份证,⼀张身份证对应⼀个⼈,是⼀个典型的⼀对⼀关系。

我们在创建一个App来对一对一模型进行演练:

写法一:

django-admin startapp Onetoone

写法二:

python manage.py startapp Onetoone

上面两种写法都可以实现创建app。

在这里插入图片描述

在这里插入图片描述

models.py

from django.db import models


# 身份证
class IDCard(models.Model):
    idcard_num = models.CharField(max_length=18, unique=True)
    address = models.CharField(max_length=200)


# 用户
class User(models.Model):
    name = models.CharField(max_length=30, unique=True) # 姓名唯一
    age = models.IntegerField(default=18)
    sex = models.BooleanField(default=True)
    # 一对一关系
    # 建立映射关系
    idcard = models.OneToOneField(IDCard, on_delete=models.PROTECT)


在这里插入图片描述

views.py

from django.shortcuts import render, HttpResponse
from Onetoone.models import *

# 一对一
# 增删改:和一对多是类似的

# 查询
def get(request):
    # 查找某用户的身份证信息
    user = User.objects.get(pk=1)
    print(user.idcard)  # 得到的是一个对象,不是查询集
    print(user.idcard.idcard_num, user.idcard.address)

    # 查找身份证对应的用户
    idcard = IDCard.objects.get(pk=1)
    print(idcard.user)  # 对象
    print(idcard.user.name, idcard.user.age, idcard.user.sex)

    return HttpResponse('查询成功!')


在这里插入图片描述

总结

在这篇博客中,我们探索了Django模型的进阶主题,重点关注了配置MySQL数据库、模型惯例以及不同表之间的关系,包括一对一、一对多和多对多关系。通过这些讲解,我们深入了解了如何在Django中使用MySQL数据库,并利用模型惯例简化开发过程。

首先,我们介绍了如何配置MySQL数据库作为Django项目的后端存储。通过正确配置数据库连接信息,我们能够与MySQL建立连接,并使用Django的ORM(对象关系映射)功能进行数据操作。

接着,我们研究了Django的模型惯例,这是一种约定俗成的规则,用于定义模型类的结构和字段。了解这些惯例有助于提高代码的可读性和可维护性,并遵循行业最佳实践。

然后,我们深入研究了不同表之间的关系。一对一关系表示两个表之间的唯一对应关系,一对多关系表示一个表中的记录可以关联到另一个表中的多个记录,而多对多关系表示两个表之间的多对多关系,需要通过中间表来进行关联。

通过具体的示例和代码片段,我们详细讲解了这些关系的定义、使用和查询方法。这些知识对于设计复杂的数据库结构和构建功能强大的应用程序至关重要。

总而言之,本文提供了关于Django模型进阶的全面指南。从配置MySQL数据库到模型惯例和不同表之间的关系,我们希望读者可以通过这些讲解提升对Django的理解和应用能力,从而构建出高效、可靠的Web应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1487000.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[BJDCTF2020]EzPHP1 --不会编程的崽

有一说一&#xff0c;这题还是有难度的 base32解码url编码绕过$_SERVER换行符绕过preg_match相同参数&#xff0c;post请求覆盖get请求&#xff0c;绕过$_REQUESTphp伪协议利用sha1数组绕过create_function代码注入 Level 1 右键源码里又发现&#xff0c;拿去base32解码即可…

w30使用python调用shell脚本

使用python脚本去实现永恒之蓝漏洞攻击 实验环境 攻击工具&#xff1a;pythonmsfconsole 靶场&#xff1a;win7 和 kali实验目的 演示python脚本调用过程 实验步骤 1.写一个永恒之蓝的攻击脚本&#xff0c;定义为blue.rc use exploit/windows/smb/ms17_010_eternalblue …

Microsoft PyRIT能自动化完成AI红队的任务

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【算法集训】基础算法:枚举

一、基本理解 枚举的概念就是把满足题目条件的所有情况都列举出来&#xff0c;然后一一判定&#xff0c;找到最优解的过程。 枚举虽然看起来麻烦&#xff0c;但是有时效率上比排序高&#xff0c;也是一个不错的方法、 二、最值问题 1、两个数的最值问题 两个数的最小值&…

【Android】View事件体系基础

文章目录 坐标系View滑动layout方法offserLeftAndRight() 和 offsetTopAndBottom()LayoutParams(布局参数)View动画scrollTo/scrollBy 解析Activity的构成 坐标系 分为Android坐标系和View坐标系 可以用 getWidth() 和 getHeight() 获取View自身的宽度和高度 对于ViewgetX() …

求Sn=a+aa+aaa+aaaa+aaaaa的前n项之和

求Snaaaaaaaaaaaaaaa的前5项之和&#xff0c;其中a是一个数字&#xff0c; 例如&#xff1a;222222222222222 int main() {int a;scanf("%d", &a);int n;scanf("%d", &n);int sum 0;int tmp 0;for (int i 0; i < n; i){tmp tmp * 10 a;sum…

bxCAN总线的工作模式和测试模式(STM32F4xx)

概述 本文主要介绍STM32F4XX的bxCAN知识&#xff0c;包括bxCAN的概念&#xff0c;各种工作模式下特性&#xff0c;如何配置各类工作模式等内容&#xff0c;还介绍了bxCAN的测试模式&#xff0c;bxCAN测试模式有3种工作类型&#xff0c;每种类型有什么特性&#xff0c;以及如何配…

C语言之指针习题一

1. 解析&#xff1a;全选 2. 解析&#xff1a;A.当内存空间释放后&#xff0c;指针将指向其他的区域&#xff0c;成为野指针 3. 解析&#xff1a;B&#xff0c;assert只会在调试模式&#xff08;debug&#xff09;下使用&#xff0c;release不会使用 4. 解析&#xff1a; A…

IDEA集成Tomcat服务器指南

目录 一.概述 二.下载安装 三.启动Tomcat服务器 四.修改端口号 五.Maven Web项目 六.创建项目 1.使用骨架 2.不使用骨架 七.Idea中集成Tomcat 1.集成本地Tomcat 2.使用Maven插件 一.概述 所谓的Web服务器软件&#xff0c;功能是对HTTP协议的操作进行封装&#xff0…

ros2的nav2_map_server导入地图时,rviz2显示no map received

ros2的nav2_map_server导入地图时&#xff0c;rviz2显示no map received 步骤&#xff1a; 1、打开终端&#xff0c;进入src/map/运行下面指令&#xff1a; ros2 run nav2_map_server map_server --ros-args --param yaml_filename:fishbot_map.yaml2、打开rviz2 rviz2通过a…

leetcode 热题 100_无重复字符的最长子串

题解一&#xff1a; 滑动窗口哈希表&#xff1a;假设字符串为"abcabcbb"&#xff0c;遍历循环所有子串&#xff0c;以不同位置作为子串的起始&#xff0c;则会得到以下最长子串。其中最长子串的右端点会随着左端点的右移而右移&#xff0c;也可能不变&#xff0c;原因…

跨平台指南:在 Windows 和 Linux 上安装 OpenSSL 的完整流程

Windows安装 一&#xff1a;找到安装包&#xff0c;双击即可 https://gitee.com/wake-up-again/installation-package.git 二&#xff1a;按照提示&#xff0c;一步一步来&#xff0c;就可以啦 三&#xff1a;此界面意思是&#xff0c;是否想向创作者捐款&#xff0c;自己视情…

访问修饰符、Object(方法,使用、equals)、查看equals底层、final--学习JavaEE的day15

day15 一、访问修饰符 含义&#xff1a; 修饰类、方法、属性&#xff0c;定义使用的范围 理解&#xff1a;给类、方法、属性定义访问权限的关键字 注意&#xff1a; ​ 1.修饰类只能使用public和默认的访问权限 ​ 2.修饰方法和属性可以使用所有的访问权限 访问修饰符本类本包…

消息中间件之RocketMQ源码分析(二十八)

延迟消息存储机制 概述 什么是延迟消息呢?延迟消息也叫定时消息&#xff0c;一般地&#xff0c;生产者在发送消息后&#xff0c;消费者希望在指定的一段时间后再消费。常规做法是&#xff0c;把信息存储在数据库中&#xff0c;使用定时任务扫描&#xff0c;符合条件的数据再…

js字符串转json的3种方法

1.eval方式解析 function strToJson(str){var json eval("(" str ")");return json;}console.log(strToJson("{int:1, string:demo}")); 运行截图&#xff1a; 注&#xff1a; 记得别忘了str两旁的小括号。 永远不要使用 eval !!! eval() 是一…

最短路径(2.19)

目录 1.网络延迟时间 弗洛伊德算法 迪杰斯特拉算法 2. K 站中转内最便宜的航班 3.从第一个节点出发到最后一个节点的受限路径数 4.到达目的地的方案数 1.网络延迟时间 有 n 个网络节点&#xff0c;标记为 1 到 n。 给你一个列表 times&#xff0c;表示信号经过 有向 边的…

3、JavaWeb-Ajax/Axios-前端工程化-Element

P34 Ajax介绍 Ajax:Asynchroous JavaScript And XML&#xff0c;异步的JS和XML JS网页动作&#xff0c;XML一种标记语言&#xff0c;存储数据&#xff0c; 作用&#xff1a; 数据交换&#xff1a;通过Ajax给服务器发送请求&#xff0c; 并获取服务器响应的数据 异步交互&am…

C++ //练习 10.24 给定一个string,使用bind和check_size在一个int的vector中查找第一个大于string长度的值。

C Primer&#xff08;第5版&#xff09; 练习 10.24 练习 10.24 给定一个string&#xff0c;使用bind和check_size在一个int的vector中查找第一个大于string长度的值。。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*****…

VsCode配置PCL、Open3D自动补全

写在前面 本文内容 在VsCode上开发PCL、Open3D相关代码&#xff0c;代码自动补全 Open3D、PCL的安装使用见各个版本的Open3D、PCL的编译、使用教程 平台/环境 windows11(windows10): visual studio 2022&#xff1b;cmake 3.22; VsCode 通过cmake构建项目&#xff1b; 转载请…

基于Springboot免费搭载轻量级阿里云OSS数据存储库(将本地文本、照片、视频、音频等上传云服务保存)

一、注册阿里云账户 打开https://www.aliyun.com/&#xff0c;申请阿里云账户并完成实名认证&#xff08;个人&#xff09;。这种情况就是完成了&#xff1a; 二、开通OSS服务 点击立即开通即可。 三、创建Bucket 申请id和secert&#xff1a; 进去创建一个Accesskey就会出现以…