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

模型进阶:

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应用程序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[spark] RDD 编程指南(翻译)

Overview 从高层次来看&#xff0c;每个 Spark 应用程序都包含一个driver program&#xff0c;该程序运行用户的main方法并在集群上执行各种并行操作。 Spark 提供的主要抽象是 resilient distributed dataset&#xff08;RDD)&#xff0c;它是跨集群节点分区的元素集合&…

【C++】结构体类

文章目录 问题提出一、结构体1.1结构体的声明1.1.1正常定义的结构体1.1.2在声明结构体的同时声明变量1.1.3typedef1.1.4成员变量 1.2结构体成员变量的使用1.2.1成员运算符 .1.2.2成员运算符 -> 1.3内存对齐1.3.1什么是内存对齐1.3.2内存对齐原则1.3.3结构体成员的定义顺序 1…

ISP代理是什么?怎么用?

在跨境出海业务中&#xff0c;代理IP对于您的在线任务至关重要&#xff0c;尤其是对于那些运行多个帐户的人来说。为您的帐户选择正确类型的代理对于确保帐户安全非常重要&#xff0c;劣质的IP容易使账号遭受封号风险。IPFoxy的多种代理IP类型应用范围各有侧重&#xff0c;其中…

Java 小项目开发日记 02(用户接口的开发)

Java 小项目开发日记 02&#xff08;用户接口的开发&#xff09; 项目目录 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&q…

2007-2022年上市公司绿色化转型数据(仅结果)

2007-2022年上市公司绿色化转型数据&#xff08;仅结果&#xff09; 1、时间&#xff1a;2007-2022年 2、范围&#xff1a;上市公司 3、来源&#xff1a;上市公司年报、上市公司社会责任报告、上市公司网站信息 4、指标&#xff1a;证券代码、年份、绿色化转型 5、方法说明…

【JAVA日志】关于日志系统的架构讨论

目录 1.日志系统概述 2.环境搭建 3.应用如何推日志到MQ 4.logstash如何去MQ中取日志 5.如何兼顾分布式链路追踪 1.日志系统概述 关于日志系统&#xff0c;其要支撑的核心能力无非是日志的存储以及查看&#xff0c;最好的查看方式当然是实现可视化。目前市面上有成熟的解决…

【Go语言】Go语言中的数组

Go语言中的数组 1 数组的初始化和定义 在 Go 语言中&#xff0c;数组是固定长度的、同一类型的数据集合。数组中包含的每个数据项被称为数组元素&#xff0c;一个数组包含的元素个数被称为数组的长度。 在 Go 语言中&#xff0c;你可以通过 [] 来标识数组类型&#xff0c;但…

瑞_Redis_Redis命令

文章目录 1 Redis命令Redis数据结构Redis 的 key 的层级结构1.0 Redis通用命令1.0.1 KEYS1.0.2 DEL1.0.3 EXISTS1.0.4 EXPIRE1.0.5 TTL 1.1 String类型1.1.0 String类型的常见命令1.1.1 SET 和 GET1.1.2 MSET 和 MGET1.1.3 INCR和INCRBY和DECY1.1.4 SETNX1.1.5 SETEX 1.2 Hash类…

Java+SpringBoot+Vue+MySQL:狱内罪犯危险性评估系统全栈开发

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

5.WEB渗透测试-前置基础知识-常用的dos命令

内容参考于&#xff1a; 易锦网校会员专享课 上一篇内容&#xff1a;4.WEB渗透测试-前置基础知识-快速搭建渗透环境&#xff08;下&#xff09;-CSDN博客 常用的100个CMD指令 1.gpedit.msc—–组策略 2. sndrec32——-录音机 3. Nslookup——-IP地址侦测器 &#xff0c;是一个…

ruoyi框架学习

RBAC模型 数据字典 拦截器 token没有&#xff0c;submit&#xff0c;request.js中&#xff0c;前端前置拦截器&#xff0c;响应拦截器 后台 注解

35岁了,还能转行做鸿蒙开发吗?

随着互联网行业的蓬勃发展时&#xff0c;不止从何时网上开始就有了&#xff1a;“程序员30岁危机、35岁中年危机”这种类似的话题&#xff0c;可以说影响了不少程序员。 人们一般常说的是三十而立&#xff0c;一个人应该对生活、职业、个人信仰等方面有了明确的认识和规划&…

【Linux】HTTP协议

目录 预备知识 认识url urlencode和urldecode http和https的区别 http request 和 http response http request格式: http reponse格式&#xff1a; HTTP的请求方法 HTTP的状态码 HTTP常见Header cookie文件 cookie是什么 问题 解决方案 预备知识 认识url 平时…

pytorch 数据集处理以及模型训练

1.基础类说明 为了统一数据的加载和处理代码&#xff0c;pytorch提供了两个类&#xff0c;用来处理数据加载&#xff1a; torch.utils.data.DataLoader torch.utils.data.Dataset 通过这两个类&#xff0c;可以使数据集加载和预处理代码&#xff0c;与模型训练代码脱钩…

10.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏发送数据的操作

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;接管游戏连接服务器的操作 码云地址&#xff08;master 分支&#xff09;&#xff1a;染指/titan 码云版本号&#xff1a;00820853d5492fa7b6e32407d46b5f9c01930ec6 代码下载地址&#xff0c;在 ti…

RTF文件格式解析(二)图像问题

图片 一个RTF文件可以包含由其他应用创建的图象。这些图象可以是16进制(默认的)或2进制格式。图象属于目标引用&#xff0c;由\pict 控制字开始。如后面的例子中将描述的&#xff0c;\pict关键字应在\*\shppict引用控制关键字之后。一个图象引用具有如下语法&#xff1a; <p…

frp 内网穿透 linux部署版

frp 内网穿透 linux部署版 前提安装 frp阿里云服务器配置测试服务器配置访问公网 前提 使用 frp&#xff0c;您可以安全、便捷地将内网服务暴露到公网&#xff0c;通过访问公网 IP 直接可以访问到内网的测试环境。准备如下&#xff1a; 公网 IP已部署好的测试服务 IP:端口号阿…

v68.指针

1.取地址运算 1.1 1.2 打印出变量的地址&#xff0c;需要使用 %p&#xff0c;注意后面加运算符 & 。注意输出地址的代码格式。%p会把这个值作地址来输出&#xff0c;输出的结果前面会加0x&#xff0c;并且以16进制的方式来输出地址 注意int 的大小是否和地址大小相同取决…

嵌入式 Linux 下的 LVGL 移植

目录 准备创建工程修改配置修改 lv_drv_conf.h修改 lv_conf.h修改 main.c修改 Makefile 编译运行更多内容 LVGL&#xff08;Light and Versatile Graphics Library&#xff0c;轻量级通用图形库&#xff09;是一个轻量化的、开源的、在嵌入式系统中广泛使用的图形库&#xff0c…

算法:动态规划全解(上)

一、动态规划初识 1.介绍 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。所以动态规划中每一个状态一定是由上一个状态推导出来的。 例如&#xff1a;有N件物品…