10 数据库表的关联
- 常见的三种关联关系:一对多,一对一,多对多
- 一对多
- 一对多的关系,就是外键关联关系
- 定义药品(Medicine)表,包括药品名称、编号和描述
- 定义订单表(Order),包括创建日期、客户、药品、数量,客户字段对应的客户只能是Customer中的某个客户记录
- Order表里面的一条订单记录的客户,对应Customer表里面的一条客户记录;一个客户记录可以对应多条订单记录,这就是一对多的关系
- 像这种一对多的关系,数据库中是用外键来表示的
- 如果一个表中的某个字段是外键,那就意味着这个外键字段的记录的取值,只能是它关联表的某个记录的主键的值
- 定义表的Model类的时候,如果没有指定主键字段,migrate的时候django会为该Model对应的数据库表自动生成一个id字段,作为主键,比如Customer和Medicine
- 定义订单表Order,客户字段就应该是一个外键,对应Customer表的主键,也就是id字段
- django中定义外键的方法就是Model类的该属性字段值为ForenignKey对象
- customer = models.ForeignKey(Customer,on_delete=models.PROTECT) :customer字段是外键,指向Customer类,也就是Order表的customer字段指向Customer表的主键的一个外键,
- on_delete指定了当我们想删除外键指向的主键记录时,系统的行为
- CASCADE:删除主键记录和相应的外键表记录
- PROTECT:禁止删除记录(除非是删除了Order表中所有跟当前要删除的Customer记录的数据)
- SET_NULL:删除主键记录,并且将外键记录中的外键字段的值置为null(前提是外键字段要设置为值允许为null)
- 外键字段实际在数据库表中的字段名:django ForeignKey定义的字段名 + 后缀_id(customer_id)
-
1 # common.models 2 from django.db import models 3 import datetime 4 5 6 class Customer(models.Model): 7 # 客户名称 8 name = models.CharField(max_length=200) 9 10 # 联系电话 11 phonenumber = models.CharField(max_length=200) 12 13 # 地址 14 address = models.CharField(max_length=200) 15 16 17 class Medicine(models.Model): 18 # 药品名 19 name = models.CharField(max_length=200) 20 # 药品编号 21 sn = models.CharField(max_length=200) 22 # 描述 23 desc = models.CharField(max_length=200) 24 25 26 class Order(models.Model): 27 # 订单名 28 name = models.CharField(max_length=200, null=True, blank=True) 29 30 # 创建日期 31 create_date = models.DateTimeField(default=datetime.datetime.now) 32 33 # 客户 34 customer = models.ForeignKey(Customer, on_delete=models.PROTECT)
- 执行python manage.py makemigrations common,python manage.py migrate common
- 一对一
- django通过OneToOneField实现一对一的关系
- django发现OneToOneField后,它会在migrate的时候,在数据库中定义该字段为外键的同时,加上unique=True约束,表示在外键的表中,该字段取值必须唯一,不能重复。
- 多对多
- BYSMS系统中,一个订单可以采购多种药品,就对应Medicine表里面的多种药品;一种药品也可以被多个订单采购。Order表和Medicine表之间就形成了多对多的关系
- medicines = models.ManyToManyField(Medicine, through='OrderMedicine') :指定Order表和Medicine表多对多的关系,其实Order表中并不会产生一个叫medicines的字段
- Order表和Medicine表多对多的关系是通过另外一张表,也就是through参数指定的OrderMedicine表来确定的
- migrate的时候,django会自动产生一张新表(common_ordermedicine)来实现Order表和Medicine表多对多的关系
- python manage.py makemigrations common python manage.py migrate common #执行这两行命令
-
1 # common.models.py 2 from django.db import models 3 import datetime 4 5 6 class Customer(models.Model): 7 # 客户名称 8 name = models.CharField(max_length=200) 9 10 # 联系电话 11 phonenumber = models.CharField(max_length=200) 12 13 # 地址 14 address = models.CharField(max_length=200) 15 16 17 class Medicine(models.Model): 18 # 药品名 19 name = models.CharField(max_length=200) 20 # 药品编号 21 sn = models.CharField(max_length=200) 22 # 描述 23 desc = models.CharField(max_length=200) 24 25 26 class Order(models.Model): 27 # 订单名 28 name = models.CharField(max_length=200, null=True, blank=True) 29 30 # 创建日期 31 create_date = models.DateTimeField(default=datetime.datetime.now) 32 33 # 客户 34 customer = models.ForeignKey(Customer, on_delete=models.PROTECT) 35 36 # 订单购买的药品,如果没有额外的字段amount的话througn='OrderMedicine'是不需要指定的,django会为我们自动生成
37 medicines = models.ManyToManyField(Medicine, through='OrderMedicine') 38 39 40 class OrderMedicine(models.Model): 41 order = models.ForeignKey(Order, on_delete=models.PROTECT) 42 medicine = models.ForeignKey(Medicine, on_delete=models.PROTECT) 43 44 # 订单中药品的数量 45 amount = models.PositiveIntegerField()
- 实现代码
- mgr目录下创建medicine.py
-
1 # bysms.urls.py 2 from django.contrib import admin 3 from django.urls import path, include 4 # 静态文件服务声明 5 from django.conf.urls.static import static 6 7 urlpatterns = [ 8 path('admin/', admin.site.urls), 9 # 全路由 10 # path('sales/orders/', list_orders), 11 # 路由子表 12 path('sales/', include('sales.urls')), 13 path('api/mgr/', include('mgr.urls')) 14 ] + static('/', document_root='./z_dist')
-
1 #mgr.urls.py 2 from django.urls import path 3 from mgr import customer, sign_in_out,medicine 4 5 urlpatterns = [ 6 path('customers', customer.dispatcher), 7 path('medicines', medicine.dispatcher), 8 path('signin', sign_in_out.signin), 9 path('signout', sign_in_out.signout), 10 ]
-
1 # mgr.medicine.py 2 import json 3 4 from django.http import JsonResponse 5 6 from common.models import Medicine 7 8 9 def mgr_login_required(view_func): 10 def wrapper(request, *args, **kwargs): 11 if 'usertype' not in request.session: 12 return JsonResponse({ 13 'ret': 302, 14 'msg': '未登录', 15 'redirect': '/mgr/sign.html' 16 }, status=302) 17 18 if request.session['usertype'] != 'mgr': 19 return JsonResponse({ 20 'ret': 302, 21 'msg': '用户非mgr类型', 22 'redirect': '/mgr/sign.html' 23 }, status=302) 24 25 return view_func(request, *args, **kwargs) 26 27 return wrapper 28 29 30 @mgr_login_required 31 def dispatcher(request): 32 if request.method == 'GET': 33 request.params = request.GET 34 35 elif request.method in ['POST', 'PUT', 'DELETE']: 36 request.params = json.loads(request.body) 37 38 action = request.params['action'] 39 if action == 'list_medicine': 40 return listmedicines(request) 41 elif action == 'add_medicine': 42 return addmedicine(request) 43 elif action == 'modify_medicine': 44 return modifymedicine(request) 45 elif action == 'del_medicine': 46 return deletemedicine(request) 47 48 else: 49 return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'}) 50 51 52 def listmedicines(request): 53 qs = Medicine.objects.values() 54 55 retlist = list(qs) 56 57 return JsonResponse({'ret': 0, 'retlist': retlist}) 58 59 60 def addmedicine(request): 61 info = request.params['data'] 62 record = Medicine.objects.create(desc=info['desc'], name=info['name'], sn=info['sn']) 63 64 return JsonResponse({ 65 "ret": 0, 66 "id": record.id 67 }) 68 69 70 def modifymedicine(request): 71 medicineid = request.params['id'] 72 newdata = request.params['newdata'] 73 74 try: 75 # 根据id 从数据库中找到相应的客户记录 76 medicine = Medicine.objects.get(id=medicineid) 77 except Medicine.DoesNotExist: 78 return { 79 'ret': 1, 80 'msg': f'id为`{medicineid}`的客户不存在' 81 } 82 83 if 'name' in newdata: 84 medicine.name = newdata['name'] 85 86 if 'desc' in newdata: 87 medicine.desc = newdata['desc'] 88 89 if 'sn' in newdata: 90 medicine.address = newdata['sn'] 91 92 # 注意,一定要执行save才能将修改的信息保存到数据库中 93 medicine.save() 94 95 return JsonResponse({'ret': 0}) 96 97 98 def deletemedicine(request): 99 medicineid = request.params['id'] 100 101 try: 102 medicine = Medicine.objects.get(id=medicineid) 103 except Medicine.DoesNotExist: 104 return { 105 'ret': 1, 106 'msg': f'id 为`{medicineid}` 的客户不存在' 107 } 108 109 # delete 方法就将该记录从数据库中删除了 110 medicine.delete() 111 return JsonResponse({'ret': 0})

浙公网安备 33010602011771号