Python 框架学习 Django篇 (六) 数据表关联_django orm 的 __ 链表,使用什么链接方式

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Python全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注Python)
img

正文

| Field | Type | Null | Key | Default | Extra |
±------------±-------------±-----±----±--------±---------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(200) | YES | | NULL | |
| create_date | datetime(6) | NO | | NULL | |
| customer_id | bigint | NO | MUL | NULL | |
±------------±-------------±-----±----±--------±---------------+
4 rows in set (0.00 sec)


![](https://img-blog.csdnimg.cn/0ab74c95d0a844e6987f94357eb90d43.png)



#### 2、一对一



> 
> **上面的外键案例,可以说是一对多或者多对一,而有时候是一对一的情况**
> 
> 
> **比如,某个学校的学生表 和学生的地址表,就形成一对一的关系,即 一条主键所在表的记录 只能对应一条 外键所在表的记录,而Django 中 用 `OneToOneField` 对象 实现 一对一 的关系**
> 
> 
> 


 vi Django\_demo/paas/models.py



class Student(models.Model):
# 姓名
name = models.CharField(max_length=200)
# 班级
classname = models.CharField(max_length=200)
# 描述
desc = models.CharField(max_length=200)

class ContactAddress(models.Model):
# 一对一 对应学生
student = models.OneToOneField(Student, on_delete=models.PROTECT)
# 家庭
homeaddress = models.CharField(max_length=200)
# 电话号码
phone = models.CharField(max_length=200)



> 
> **Django发现这样一对一定定义,它会在migrate的时候,在数据库中定义该字段为外键的同时, 加上 `unique=True` 约束,表示在此表中,所有记录的该字段 取值必须唯一,不能重复**
> 
> 
> 


#### 


####  3、多对多



> 
> **数据库中还存在一种多对多的关系,在order订单表中**
> 
> 
> 
> **一个订单可以采购多种药品,就对应 Medicine表里面的多种药品;**
> 
> 
> 
> **而一种药品也可以被多个订单采购, 那么Order表 和 Medicine表 之间就形成了多对多的关系**
> 
> 
> 


 ![](https://img-blog.csdnimg.cn/a009daf6a0444deebe1f1976df080623.png)



> 
> **Django是通过 `ManyToManyField` 对象 表示 多对多的关系的**
> 
> 
> 


 vi Django\_demo/paas/models.py



import datetime
class Order(models.Model):
# 订单名
name = models.CharField(max_length=200,null=True,blank=True)

# 创建日期
create_date = models.DateTimeField(default=datetime.datetime.now)

# 客户
customer = models.ForeignKey(Customer,on_delete=models.PROTECT)

# 订单购买的药品,和Medicine表是多对多 的关系
medicines = models.ManyToManyField(Medicine, through='OrderMedicine')

class OrderMedicine(models.Model):
#添加外键
order = models.ForeignKey(Order, on_delete=models.PROTECT)
medicine = models.ForeignKey(Medicine, on_delete=models.PROTECT)

# 订单中药品的数量  一种特殊的类型,表示非负整数
amount = models.PositiveIntegerField()  


> 
> **我们上面通过medicines = models.ManyToManyField(Medicine, through='OrderMedicine')**
> 
> 
> 
> **去指定Order表和Medicine表的对应关系,其实不会在Order表上面创建medicines的字段**
> 
> 
> 



python manage.py makemigrations
python manage.py migrate

#查看
desc paas_OrderMedicine;


 ![](https://img-blog.csdnimg.cn/d4f3c683bc394887ba1c5d57e8b1d69d.png)



#### 4、管理药品实现



> 
> **我们在 mgr 目录下面新建 medicine.py,处理 客户端发过来的 列出药品、添加药品、修改药品、删除药品 的请求,需要运用前面的数据库增删改查的方法**
> 
> 
> 


vi Django\_demo/mgr/medicine.py



from django.http import JsonResponse

导入 Medicine 对象定义(这块可能显示模块导入不正常,忽略)

from paas.models import Medicine

import json

def Orderdispatcher(request):
# 根据session判断用户是否是登录的管理员用户
if ‘usertype’ not in request.session:
return JsonResponse({
‘ret’: 302,
‘msg’: ‘未登录’,
‘redirect’: ‘/mgr/sign.html’},
status=302)

if request.session['usertype'] != 'mgr':
    return JsonResponse({
        'ret': 302,
        'msg': '用户非mgr类型',
        'redirect': '/mgr/sign.html'},
        status=302)


# 将请求参数统一放入request 的 params 属性中,方便后续处理

# GET请求 参数 在 request 对象的 GET属性中
if request.method == 'GET':
    request.params = request.GET

# POST/PUT/DELETE 请求 参数 从 request 对象的 body 属性中获取
elif request.method in ['POST','PUT','DELETE']:
    # 根据接口,POST/PUT/DELETE 请求的消息体都是 json格式
    request.params = json.loads(request.body)


# 根据不同的action分派给不同的函数进行处理
action = request.params['action']
if action == 'list_medicine':
    return listmedicine(request)
elif action == 'add_medicine':
    return addmedicine(request)
elif action == 'modify_medicine':
    return modifymedicine(request)
elif action == 'del_medicine':
    return deletemedicine(request)

else:
    return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})

def listmedicine(request):
# 返回一个 QuerySet 对象 ,包含所有的表记录
qs = Medicine.objects.values()

# 将 QuerySet 对象 转化为 list 类型
# 否则不能 被 转化为 JSON 字符串
retlist = list(qs)

return JsonResponse({'ret': 0, 'retlist': retlist})

def addmedicine(request):

info    = request.params['data']

# 从请求消息中 获取要添加客户的信息
# 并且插入到数据库中
medicine = Medicine.objects.create(name=info['name'] ,
                                   sn=info['sn'] ,
                                   desc=info['desc'])


return JsonResponse({'ret': 0, 'id':medicine.id})

def modifymedicine(request):

# 从请求消息中 获取修改客户的信息
# 找到该客户,并且进行修改操作

medicineid = request.params['id']
newdata    = request.params['newdata']

try:
    # 根据 id 从数据库中找到相应的客户记录
    medicine = Medicine.objects.get(id=medicineid)
except Medicine.DoesNotExist:
    return  {
        'ret': 1,
        'msg': f'id 为`{medicineid}`的药品不存在'
    }


if 'name' in  newdata:
    medicine.name = newdata['name']
if 'sn' in  newdata:
    medicine.sn = newdata['sn']
if 'desc' in  newdata:
    medicine.desc = newdata['desc']

# 注意,一定要执行save才能将修改信息保存到数据库
medicine.save()

return JsonResponse({'ret': 0})

def deletemedicine(request):

medicineid = request.params['id']

try:
    # 根据 id 从数据库中找到相应的药品记录
    medicine = Medicine.objects.get(id=medicineid)
except Medicine.DoesNotExist:
    return  {
        'ret': 1,
        'msg': f'id 为`{medicineid}`的客户不存在'
    }

# delete 方法就将该记录从数据库中删除了
medicine.delete()

return JsonResponse({'ret': 0})


**添加路由**


vi Django\_demo/mgr/urls.py



from django.urls import path

from .k8s import dispatcher
from .sign_in_out import signin,signout

from .medicine import orderdispatcher #添加
urlpatterns = [
path(‘customers/’, dispatcher),
path(‘medicines/’, orderdispatcher), #添加 必须带斜杠

path('signin', signin),
path('signout', signout),

]



#### 


#### 5、添加药品


vi main.py



import requests,pprint

#添加认证
payload = {
‘username’: ‘root’,
‘password’: ‘12345678’
}
#发送登录请求
response = requests.post(‘http://127.0.0.1:8000/api/mgr/signin’,data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get(‘Set-Cookie’)

构建添加 客户信息的 消息体,是json格式

payload = {
“action”:“add_medicine”,
“data”:{
“name”:“板蓝根”,
“sn”:“133”,
“desc”:“感冒药”
}
}
url=‘http://127.0.0.1:8000/api/mgr/medicines/’
if set_cookie:
# 将Set-Cookie字段的值添加到请求头中
headers = {‘Cookie’: set_cookie}

# 发送请求给web服务
response = requests.post(url,json=payload,headers=headers)
pprint.pprint(response.json())

**json类型说明**



> 
> **刚才上面我们使用了查询和添加数据,但是发现一个问题,两个请求传参的时候稍有不同**
> 
> 
> 



#data=payload 表示这个请求携带的参数是以表单的形式也就是字符串形式传输给后端的
requests.post(url,data=payload)

#json=payload 表示参数是以json的形式传输给后端的
requests.post(url,json=payload)



> 
> **在使用时要特别注意,我卡了半天才看到。。** 
> 
> 
> 


#### 


#### 6、查询药品


vi main.py



import requests,pprint

payload = {
‘username’: ‘root’,
‘password’: ‘12345678’
}
#发送登录请求
response = requests.post(‘http://127.0.0.1:8000/api/mgr/signin’,data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get(‘Set-Cookie’)
if set_cookie:
# 将Set-Cookie字段的值添加到请求头中
headers = {‘Cookie’: set_cookie}

# 发送带有Cookie的新请求 修改url到新的路由
response = requests.get('http://127.0.0.1:8000/api/mgr/medicines/?action=list_medicine',headers=headers)
pprint.pprint(response.json())

返回



{‘ret’: 0,
‘retlist’: [{‘desc’: ‘192.168.1.2’, ‘id’: 1, ‘name’: ‘abc’, ‘sn’: ‘133’},
{‘desc’: ‘感冒药’, ‘id’: 2, ‘name’: ‘板蓝根’, ‘sn’: ‘133’}]}



> 
> **第一行是我写错了添加上的,一会当作删除的案例**
> 
> 
> 


**遇到的问题**



> 
> **在访问url的时候,要确定url访问时是否需要带上/  如果定义的urls上有/,那边必须要带上斜杠不然会报错**
> 
> 
> 



#### 7、修改药品


vi main.py



import requests,pprint

#添加认证
payload = {
‘username’: ‘root’,
‘password’: ‘12345678’
}
#发送登录请求
response = requests.post(‘http://127.0.0.1:8000/api/mgr/signin’,data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get(‘Set-Cookie’)

构建添加 客户信息的 消息体,是json格式

payload = {
“action”:“modify_medicine”,
“id”: “1”,
“newdata”:{
“name”:“诺氟沙星”,
“sn”:“141”,
“desc”:“无”
}
}
url=‘http://127.0.0.1:8000/api/mgr/medicines/’

if set_cookie:
# 将Set-Cookie字段的值添加到请求头中
headers = {‘Cookie’: set_cookie}

# 发送请求给web服务
response = requests.post(url,json=payload,headers=headers)
pprint.pprint(response.json())

再次查询



{‘ret’: 0,
‘retlist’: [{‘desc’: ‘无’, ‘id’: 1, ‘name’: ‘诺氟沙星’, ‘sn’: ‘141’},
{‘desc’: ‘感冒药’, ‘id’: 2, ‘name’: ‘板蓝根’, ‘sn’: ‘133’}]}


#### 8、删除药品



import requests,pprint

#添加认证
payload = {
‘username’: ‘root’,
‘password’: ‘12345678’
}
#发送登录请求
response = requests.post(‘http://127.0.0.1:8000/api/mgr/signin’,data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get(‘Set-Cookie’)

构建添加 客户信息的 消息体,是json格式

payload = {
“action”:“del_medicine”,
“id”:“1”,
}
url=‘http://127.0.0.1:8000/api/mgr/medicines/’

if set_cookie:
# 将Set-Cookie字段的值添加到请求头中
headers = {‘Cookie’: set_cookie}

在这里插入图片描述

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注python)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
rmark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poaWd1aWd1,size_16,color_FFFFFF,t_70)

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注python)
[外链图片转存中…(img-NGbfq27u-1713159756467)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值