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

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

时间:2024-08-07 09:57:18浏览次数:21  
标签:Python 数据库 request Medicine Django models ORM medicine id

在这里插入图片描述

前言: 零基础学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的使用。

标签:Python,数据库,request,Medicine,Django,models,ORM,medicine,id
From: https://blog.csdn.net/weixin_51390582/article/details/140674833

相关文章

  • Python从0到100(五十):深入理解Django ORM与事务处理
    前言:零基础学Python:Python从0到100最新最全教程。想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、计算机视觉、机器学习、神经网络以及人工智能相关知......
  • 界面控件DevExpress WinForms,支持HTML & CSS提升用户体验(二)
    DevExpressWinForms现在可以利用HTML/CSS强大的功能,帮助受DevExpress驱动的WinForms应用程序引入现代的UI元素和用户体验!P.S:DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能完美构建流畅、美观且易于使用的应......
  • python 实现FFT快速傅立叶变换算法
    FFT快速傅里叶变换介绍FFT(快速傅里叶变换)是计算离散傅里叶变换(DFT)及其逆变换的一种高效算法。DFT是一种将信号从时域转换到频域的数学工具,而FFT通过减少计算量来加速这一过程。FFT的基本思想FFT利用了DFT中的对称性和周期性,通过分而治之的策略将DFT分解为更小的DFT,从而显......
  • 8 Python字符串与二进制文本相互转换
     欢迎来到@一夜看尽长安花博客,您的点赞和收藏是我持续发文的动力对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:3329759426@qq.com。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。   专栏:java全栈C&C++PythonAIP......
  • 7 Python之代码类型提示(Type Hint)
     欢迎来到@一夜看尽长安花博客,您的点赞和收藏是我持续发文的动力对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:3329759426@qq.com。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。   专栏:java全栈C&C++PythonAIP......
  • Python 内联函数最佳实践
    如果我有一个可以用一行表示的python函数,那么以下哪一个选项通常被认为最适合可读性和一般最佳实践?或者还有其他更好的选择吗?选项2对我来说似乎是最好的,但我是初学者,所以我不想假设任何事情。我尝试过搜索PEP8、StackOverflow和一两个博客,但我找不到任何关于python的明......
  • 在Python中抽象出具有相同接口的真实硬件和模拟设备
    我正在寻找一种更惯用或更简洁的OOP模式来实现与以下内容等效的功能。接口和实现fromabcimportABC,abstractmethodfromtypingimportoverrideclassDevice:"""Maininterfacethathideswhetherthedeviceisarealhardwaredeviceorasimulated......
  • Python Django,使用外部MSSQL数据库
    我正在尝试创建一个连接到外部MSSQL数据库以仅检索信息(只读)的django网站。这个数据库非常庞大,有数百个表。我目前可以通过在django应用程序中创建一个函数来使其工作,该函数使用connectionString并运行原始SQL查询并将其返回到pandas数据帧中。不知何故,我感觉......
  • 使用 Python 中的 Matplotlib 和时间序列索引生成奇怪的图
    我正在尝试使用Python中的Matplotlib绘制一些时间序列数据,但生成的图看起来很奇怪,我不明白为什么。这是我正在使用的代码:filtered_df=df.loc[(df.index>'2010-01-01')&(df.index<='2010-01-08')]#Plottingthedatafig,axs=plt.subplots(1,1,figsize=(12,......
  • Dash Python:通过 @callback 链接选项卡
    这个问题是下面链接的问题的扩展:DashPython:布局函数中的@Callback未被调用我有一个简单的数据框:importpandasaspddf=pd.DataFrame({'Class1':[1,2,3,4,5],'Class2':[6,7,8,9,10]})我创建了一个数据提取函数,该函数根......