Python从0到100(四十九):数据库设计及Django ORM使用

在这里插入图片描述

前言: 零基础学Python:Python从0到100最新最全教程 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学习学习和学业的先行者!
欢迎大家订阅专栏:零基础学Python:Python从0到100最新最全教程!

在后端系统开发中,数据库设计是至关重要的一环。尤其是在前后端分离的系统中,后端的核心职责就是数据管理。因此,了解和掌握数据库设计的基本理念和实践是每个后端开发者的必备技能。本文将从关系型数据库的基本概念出发,详细讲解如何在Django框架中设计和实现数据库模型,并通过代码示例展示如何在实际项目中应用这些设计。

一、关系型数据库基础

关系型数据库是建立在关系模型基础上的数据库,其核心思想是通过表(Table)和表之间的关系来组织数据。常见的关系型数据库系统包括MySQL、Oracle、SQL Server和SQLite等。与关系型数据库相对的是非关系型数据库(如MongoDB、Cassandra),它们不依赖于表和关系,而是通过其他方式(如文档、键值对等)来存储数据。

1.1 表和表之间的关系

在关系型数据库中,表之间的关系是设计的关键。常见的关系类型有:

  • 一对多(One-to-Many):一个表中的记录可以对应另一个表中的多条记录。例如,一个客户可以有多个订单。
  • 一对一(One-to-One):一个表中的记录只能对应另一个表中的一条记录。例如,一个学生只能有一个家庭地址。
  • 多对多(Many-to-Many):一个表中的记录可以对应另一个表中的多条记录,反之亦然。例如,一个订单可以包含多种药品,而一种药品也可以出现在多个订单中。

二、Django ORM 模型设计

Django是一个高级的Python Web框架,它提供了一个强大的对象关系映射(ORM)系统,使得开发者可以用Python代码来定义数据库模型,而不需要直接编写SQL语句。下面将通过几个示例来展示如何在Django中设计数据库模型。

2.1 一对多关系

表之间 一对多 的关系,就是 外键 关联关系
在此models模块中,我们将qq删去:
在这里插入图片描述
因为在数据库中也有我们的qq数据,我们需要执行命令将其删去:

python manage.py makemigrations

在这里插入图片描述
然后执行命令运行qq删去:

python manage.py migrate

在这里插入图片描述
此时我们打开数据库,会发现其中的qq信息已经被我们删去了!
在这里插入图片描述

在Django中,一对多关系通过ForeignKey字段来实现。假设我们有一个Customer模型和一个Order模型,其中每个订单都关联到一个客户。

from django.db import models
import datetime

class Customer(models.Model):
    name = models.CharField(max_length=200)
    phonenumber = models.CharField(max_length=200)
    address = models.CharField(max_length=200)

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)

在这个例子中,Order模型中的customer字段是一个外键,指向Customer模型的主键(默认为id)。on_delete=models.PROTECT参数表示当尝试删除一个客户时,如果存在关联的订单,Django会抛出异常,防止删除操作。

2.2 一对一关系

一对一关系通过OneToOneField字段来实现。假设我们有一个Student模型和一个ContactAddress模型,每个学生都有一个唯一的联系地址。

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)

在这个例子中,ContactAddress模型中的student字段是一个一对一外键,指向Student模型的主键。Django会自动为这个字段添加unique=True约束。

2.3 多对多关系

在我们的 BYSMS系统中, 一个订单可以采购多种药品,就对应 Medicine表里面的多种药品;而一种药品也可以被多个订单采购, 那么Order表 和 Medicine表 之间就形成了多对多的关系。

其对应关系可以用下图来表示:
在这里插入图片描述
多对多关系通过ManyToManyField字段来实现。假设我们有一个Order模型和一个Medicine模型,每个订单可以包含多种药品,而一种药品也可以出现在多个订单中。

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)
    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')

将其放到我们的model文件中:
在这里插入图片描述

指定Order表和 Medicine 表 的多对多关系, 其实Order表中并不会产生一个 叫 medicines 的字段。
Order表和 Medicine 表 的多对多关系 是 通过另外一张表, 也就是 through 参数 指定的 OrderMedicine 表 来确定的。
migrate的时候,Django会自动产生一张新表 (这里就是 common_ordermedicine)来 实现 order 表 和 medicine 表之间的多对多的关系。
大家可以执行下面两行命令 migrate 试一下:

python manage.py makemigrations common
python manage.py migrate

在这里插入图片描述
就会发现产生如下的一张新表 common_ordermedicine:
在这里插入图片描述
可以发现这张表中有 order_idmedicine_id 两个字段。
比如一个order表的订单id 为 1, 如果该订单中对应的药品有3种,它们的id分别 为 3,4,5。 那么就会有类似这样的这样3条记录在 common_order_medicine 表中。
在这里插入图片描述

在这个例子中,Order模型中的medicines字段是一个多对多字段,通过OrderMedicine模型来实现关联。OrderMedicine模型包含order_idmedicine_id字段,以及一个表示药品数量的amount字段。

三、数据库迁移

在Django中,数据库迁移是一个重要的步骤,用于将模型定义同步到数据库中。以下是执行迁移的基本命令:

python manage.py makemigrations
python manage.py migrate

这些命令会根据模型定义生成迁移文件,并应用这些迁移到数据库中,从而创建或更新数据库表。

四、实现代码

在实际项目中,除了定义模型外,还需要编写相应的视图和URL路由来处理前端的请求。以下是一个简单的示例,展示如何在Django中处理药品管理的增删改查操作。

4.1 视图函数
from django.http import JsonResponse
from common.models import Medicine

def dispatcher(request):
    if 'usertype' not in request.session or request.session['usertype'] != 'mgr':
        return JsonResponse({
            'ret': 302,
            'msg': '未登录或用户非mgr类型',
            'redirect': '/mgr/sign.html'},
            status=302)

    request.params = request.GET if request.method == 'GET' else json.loads(request.body)

    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):
    qs = Medicine.objects.values()
    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:
        medicine = Medicine.objects.get(id=medicineid)
    except Medicine.DoesNotExist:
        return JsonResponse({'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']
    medicine.save()
    return JsonResponse({'ret': 0})

def deletemedicine(request):
    medicineid = request.params['id']
    try:
        medicine = Medicine.objects.get(id=medicineid)
    except Medicine.DoesNotExist:
        return JsonResponse({'ret': 1, 'msg': f'id 为`{medicineid}`的药品不存在'})
    medicine.delete()
    return JsonResponse({'ret': 0})
4.2 URL路由
from django.urls import path
from mgr import customer, sign_in_out, medicine, order

urlpatterns = [
    path('customers', customer.dispatcher),
    path('medicines', medicine.dispatcher),
    path('signin', sign_in_out.signin),
    path('signout', sign_in_out.signout),
]

通过上述代码,我们可以处理来自前端的药品管理请求,实现药品的增删改查功能。

五、总结

在本文中,我们详细讲解了关系型数据库的基本概念,并通过Django ORM展示了如何在实际项目中设计和实现数据库模型。通过代码示例,我们展示了如何处理药品管理的增删改查操作。希望这些内容能帮助你更好地理解和掌握数据库设计和Django ORM的使用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是Dream呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值