建立一个更高级别的查询 API:正确使用Django ORM 的方式

Django REST framework:构建高效RESTful API的终极指南 RESTful API是现代Web开发的核心技术,遵循资源表述状态转移架构风格。Django REST framework(DRF)作为Django生态中的API开发工具包,通过序列化器、视图集和路由等组件,实现了高效的数据交互和业务逻辑封装。其内置的认证系统支持Session、Token和JWT等多种方式,而可浏览API界面则大幅提升了开发体验。在电商平台、内容管理系统等场景中,DRF的ModelSerializer能自动处理Django模型关系,配合ViewSets可快速实现CRUD操作。相比Flask 阅读详情

http://www.oschina.net/translate/higher-level-query-api-django-orm

英文原文:Using Django's low-level ORM query methods directly in a view is (usually) an anti-pattern.


摘要

在这篇文章里,我将以反模式的角度来直接讨论Django的低级ORM查询方法的使用。作为一种替代方式,我们需要在包含业务逻辑的模型层建立与特定领域相关的查询API,这些在Django中做起来不是非常容易,但通过深入地了解ORM的内容原理,我将告诉你一些简捷的方式来达到这个目的。

概览

当编写Django应用程序时,我们已经习惯通过添加方法到模型里以此达到封装业务逻辑并隐藏实现细节。这种方法看起来是非常的自然,而且实际上它也用在Django的内建应用中。

?
1
2
3
4
>>>  from django.contrib.auth.models  import User
>>> user  = User.objects.get(pk = 5 )
>>> user.set_password( 'super-sekrit' )
>>> user.save()
这里的set_password就是一个定义在django.contrib.auth.models.User模型中的方法,它隐藏了对密码进行哈希操作的具体实现。相应的代码看起来应该是这样:
?
1
2
3
4
5
6
7
8
from django.contrib.auth.hashers  import make_password
 
class User(models.Model):
 
     # fields go here..
 
     def set_password( self , raw_password):
         self .password  = make_password(raw_password)
晴风晓月
晴风晓月
翻译于 2年前

2人顶

顶 翻译的不错哦!

我们正在使用Django,建立一个特定领域的顶部通用接口,低等级的ORM工具。在此基础上,增加抽象等级,减少交互代码。这样做的好处是使代码更具可读性、重用性和健壮性。

我们已经在单独的例子中这样做了,下面将会把它用在获取数据库信息的例子中。

为了描述这个方法,我们使用了一个简单的app(todo list)来说明。

注意:这是一个例子。因为很难用少量的代码展示一个真实的例子。不要过多的关心todo list继承他自己,而要把重点放在如何让这个方法运行。

下面就是models.py文件:
?
1
2
3
4
5
6
7
8
9
from django.db  import models
 
PRIORITY_CHOICES  = [( 1 ,  'High' ), ( 2 ,  'Low' )]
 
class Todo(models.Model):
     content  = models.CharField(max_length = 100 )
     is_done  = models.BooleanField(default = False )
     owner  = models.ForeignKey( 'auth.User' )
     priority  = models.IntegerField(choices = PRIORITY_CHOICES, default = 1
Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

想像一下,我们将要传递这些数据,建立一个view,来为当前用户展示不完整的,高优先级的 Todos。这里是代码: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
def dashboard(request):
 
     todos  = Todo.objects. filter (
         owner = request.user
     ). filter (
         is_done = False
     ). filter (
         priority = 1
     )
 
     return render(request,  'todos/list.html' , {
         'todos' : todos,
     })

注意:这里可以写成request.user.todo_set.filter(is_done=False, priority=1)。但是这里只是一个实验。

为什么这样写不好呢?

首先,代码冗长。七行代码才能完成,正式的项目中,将会更加复杂。

其次,泄露实现细节。比如代码中的is_done是BooleanField,如果改变了他的类型,代码就不能用了。

然后就是,意图不清晰,很难理解。

最后,使用中会有重复。例:你需要写一行命令,通过cron,每周发送给所有用户一个todo list,这时候你就需要复制-粘贴着七行代码。这不符合DRY(do not repeat yourself)

Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

让我们大胆的猜测一下:直接使用低等级的ORM代码是反模式的。

如何改进呢? 

使用 Managers 和 QuerySets 

首先,让我们先了解一下概念。

Django 有两个关系密切的与表级别操作相关的构图:managers 和 querysets

manager(django.db.models.manager.Manager的一个实例)被描述成 “通过查询数据库提供给Django的插件”。Manager是表级别功能的通往ORM大门。每一个model都有一个默认的manager,叫做objects。

Quesyset  (django.db.models.query.QuerySet) 是“数据库中objects的集合”。本质上是一个SELECT查询,也可以使用过滤,排序等(filtered,ordered),来限制或者修改查询到的数据。用来  创建或操纵 django.db.models.sql.query.Query实例,然后通过数据库后端在真正的SQL中查询。 

啊?你还不明白?

随着你慢慢深入的了解ORM,你就会明白Manager和QuerySet之间的区别了。

Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

人们会被所熟知的Manager接口搞糊涂,因为他并不是看上去那样。

Manager接口就是个谎言。

QuerySet方法是可链接的。每一次调用QuerySet的方法(如:filter)都会返回一个复制的queryset等待下一次的调用。这也是Django ORM 流畅之美的一部分。

但是当Model.objects 是一个 Manager时,就出现问题了。我们需要调用objects作为开始,然后链接到结果的QuerySet上去。

那么Django又是如何解决呢?

接口的谎言由此暴露,所有的QuerySet 方法基于Manager。在这个方法中,通过self.get_query_set()的代理,重新创建一个QuerySet。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Manager( object ):
 
     # SNIP some housekeeping stuff..
 
     def get_query_set( self ):
         return QuerySet( self .model, using = self ._db)
 
     def all ( self ):
         return self .get_query_set()
 
     def count( self ):
         return self .get_query_set().count()
 
     def filter ( self ,  * args,  * * kwargs):
         return self .get_query_set(). filter ( * args,  * * kwargs)
 
     # and so on for 100+ lines...
更多代码,请参照Manager的资源文件。
Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

让我们立刻回到todo list ,解决query接口的问题。Django推荐的方法是自定义Manager子类,并加在models中。 

你也可以在model中增加多个managers,或者重新定义objects,也可以维持单个的manager,增加自定义方法。 

下面让我们实验一下这几种方法: 

方法1:多managers
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class IncompleteTodoManager(models.Manager):
     def get_query_set( self ):
         return super (TodoManager,  self ).get_query_set(). filter (is_done = False )
 
class HighPriorityTodoManager(models.Manager):
     def get_query_set( self ):
         return super (TodoManager,  self ).get_query_set(). filter (priority = 1 )
 
class Todo(models.Model):
     content  = models.CharField(max_length = 100 )
     # other fields go here..
 
     objects  = models.Manager()  # the default manager
 
     # attach our custom managers:
     incomplete  = models.IncompleteTodoManager()
     high_priority  = models.HighPriorityTodoManager()
这个接口将以这样的方式展现:
?
1
2
>>> Todo.incomplete. all ()
>>> Todo.high_priority. all ()
这个方法有几个问题。
Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

第一,这种实现方式比较啰嗦。你要为每一个query自定义功能定义一个class。

第二,这将会弄乱你的命名空间。Django开发者吧Model.objects看做表的入口。这样做会破坏命名规则。

第三,不可链接的。这样做不能将managers组合在一起,获得不完整,高优先级的todos,还是回到低等级的ORM代码:Todo.incomplete.filter(priority=1) 或Todo.high_priority.filter(is_done=False)

综上,使用多managers的方法,不是最优选择。
Naixjs
Naixjs
翻译于 2年前

1人顶

顶 翻译的不错哦!

方法2: Manager 方法

现在,我们试下其他Django允许的方法:在单个自定义Manager中的多个方法

?
1
2
3
4
5
6
7
8
9
10
11
12
class TodoManager(models.Manager):
     def incomplete( self ):
         return self . filter (is_done = False )
 
     def high_priority( self ):
         return self . filter (priority = 1 )
 
class Todo(models.Model):
     content  = models.CharField(max_length = 100 )
     # other fields go here..
 
     objects  = TodoManager()
我们的API 现在看起来是这样: 
?
1
2
>>> Todo.objects.incomplete()
>>> Todo.objects.high_priority()

这个方法显然更好。它没有太多累赘(只有一个Manager类)并且这种查询方法很好地在对象后预留命名空间。(译注:可以很形象、方便地添加更多的方法)

不过这还不够全面。  Todo.objects.incomplete() 返回一个普通查询,但我们无法使用 Todo.objects.incomplete().high_priority() 。我们卡在  Todo.objects.incomplete().filter(is_done=False),没有使用。
fkkeee
fkkeee
翻译于 2年前

1人顶

顶 翻译的不错哦!

方法3:自定义QuerySet

现在我们已进入Django尚未开放的领域,Django文档中找不到这些内容。。。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TodoQuerySet(models.query.QuerySet):
     def incomplete( self ):
         return self . filter (is_done = False )
 
     def high_priority( self ):
         return self . filter (priority = 1 )
 
class TodoManager(models.Manager):
     def get_query_set( self ):
         return TodoQuerySet( self .model, using = self ._db)
 
class Todo(models.Model):
     content  = models.CharField(max_length = 100 )
     # other fields go here..
 
     objects  = TodoManager()

我们从以下调用的视图代码中可以看出端倪:

?
1
2
3
4
5
>>> Todo.objects.get_query_set().incomplete()
>>> Todo.objects.get_query_set().high_priority()
>>>  # (or)
>>> Todo.objects. all ().incomplete()
>>> Todo.objects. all ().high_priority()

差不多完成了!这并没有比第2个方法多多少累赘,却得到方法2同样的好处,和额外的效果(来点鼓声吧...),它终于可链式查询了!

?
1
>>> Todo.objects. all ().incomplete().high_priority()

然而它还不够完美。这个自定义的Manager仅仅是一个样板而已,而且 all() 还有瑕疵,在使用时不好把握,而更重要的是不兼容,它让我们的代码看起来有点怪异。

fkkeee
fkkeee
翻译于 2年前

1人顶

顶 翻译的不错哦!

方法3a:复制Django,代理做所有事

现在我们让以上”假冒Manager API“讨论变得有用:我们知道如何解决这个问题。我们简单地在Manager中重新定义所有QuerySet方法,然后代理它们返回我们自定义QuerySet:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TodoQuerySet(models.query.QuerySet):
     def incomplete( self ):
         return self . filter (is_done = False )
 
     def high_priority( self ):
         return self . filter (priority = 1 )
 
class TodoManager(models.Manager):
     def get_query_set( self ):
         return TodoQuerySet( self .model, using = self ._db)
 
     def incomplete( self ):
         return self .get_query_set().incomplete()
 
     def high_priority( self ):
         return self .get_query_set().high_priority()
这个能更好地提供我们想要的API: 
?
1
>>> Todo.objects.incomplete().high_priority()  # yay!

除上面那些输入部分、且非常不DRY,每次你新增一个文件到QuerySet,或是更改现有的方法标记,你必须记住在你的Manager中做相同的更改,否则它可能不会正常工作。这是配置的问题。

fkkeee
fkkeee
翻译于 2年前

2人顶

顶 翻译的不错哦!

方法3b: django-model-utils 

Python 是一种动态语言。 我们就一定能避免所有模块?一个名叫Django-model-utils的第三方应用带来的一点小忙,就会有点不受控制了。先运行 pip install django-model-utils ,然后……
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from model_utils.managers  import PassThroughManager
 
class TodoQuerySet(models.query.QuerySet):
     def incomplete( self ):
         return self . filter (is_done = False )
 
     def high_priority( self ):
         return self . filter (priority = 1 )
 
class Todo(models.Model):
     content  = models.CharField(max_length = 100 )
     # other fields go here..
 
     objects  = PassThroughManager.for_queryset_class(TodoQuerySet)()
这要好多了。我们只是象之前一样  简单地定义了自定义QuerySet子类,然后通过django-model-utils提供的PassThroughManager类附加这些QuerySet到我们的model中。 

PassThroughManager 是由__getattr__ 实现的,它能阻止访问到django定义的“不存在的方法”,并且自动代理它们到QuerySet。这里需要小心一点,检查确认我们没有在一些特性中没有无限递归(这是我为什么推荐使用django-model-utils所提供的用不断尝试测试的方法,而不是自己手工重复写)。 

做这些有什么帮助?

记得上面早些定义的视图代码么?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
def dashboard(request):
 
     todos  = Todo.objects. filter (
         owner = request.user
     ). filter (
         is_done = False
     ). filter (
         priority = 1
     )
 
     return render(request,  'todos/list.html' , {
         'todos' : todos,
     })
加点小改动,我们让它看起来象这样:
?
1
2
3
4
5
6
7
8
9
def dashboard(request):
 
     todos  = Todo.objects.for_user(
         request.user
     ).incomplete().high_priority()
 
     return render(request,  'todos/list.html' , {
         'todos' : todos,
     })
希望你也能同意第二个版本比第一个更简便,清晰并且更有可读性。 
Django能帮忙么?
fkkeee
fkkeee
翻译于 2年前

3人顶

顶 翻译的不错哦!

让这整个事情更容易的方法,已经在django开发邮件列表中讨论过,并且得到一个相关票据(译注:associated ticket叫啥名更好?)。Zachary Voase则建议如下:

?
1
2
3
4
5
class TodoManager(models.Manager):
 
     @models .querymethod
     def incomplete(query):
         return query. filter (is_done = False )

通过这个简单的装饰方法的定义,让Manager和QuerySet都能使不可用的方法神奇地变为可用。

我个人并不完全赞同使用基于装饰方法。它略过了详细的信息,感觉有点“嘻哈”。我感觉好的方法,增加一个QuerSet子类(而不是Manager子类)是更好,更简单的途径。

或者我们更进一步思考。退回到在争议中重新审视Django的API设计决定时,也许我们能得到真实更深的改进。能不再争吵Managers和QuerySet的区别吗(至少澄清一下)?
fkkeee
fkkeee
翻译于 2年前

2人顶

顶 翻译的不错哦!

我很确信,不管以前是否曾经有过这么大的重构工作,这个功能必然要在Django 2.0 甚至更后的版本中。

因此,简单概括一下: 

在视图和其他高级应用中使用源生的ORM查询代码不是很好的主意。而是用django-model-utils中的PassThroughManager将我们新加的自定义QuerySet API加进你的模型中,这能给你以下好处:

    啰嗦代码少,并且更健壮。 
    增加DRY,增强抽象级别。 

   将所属的业务逻辑推送至对应的域模型层。

感谢阅读!

fkkeee
fkkeee
翻译于 2年前

2人顶

顶 翻译的不错哦!

Modelsim10.5_se安装(Win11) modelsim是Mentor公司开发的优秀的HDL语言仿真软件。它能提供友好的仿真环境,采用单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术和单一内核仿真技术,编译仿真速度快且编译的代码与平台无关。 阅读详情

相关推荐

驱动兼容_FANUC 驱动器兼容问题探讨

近10年来,FANUC伺服驱动器随着系统的升级而升级,不同的系统,可以兼容很多种类的驱动器,作者做了一些常见经验总结如下表:电源模块伺服放大器主轴放大器bi一体18i/OIB/OIC6110-Hxxx6114-Hxxx6111-Hxxx6134-Hxxx31iA/OID6140-Hxxx6117-Hxxx6141-Hxxx6164-Hxxx31IB/35IB/OIF/OI MATE D(5包)62...

weixin_34420941的博客 1751

全字段多条件搜索(api接口)

近期在做项目时遇到了一个全表全字段多条件搜索的需求,在平时搜索最常见的就是 字段+like +‘% 条件%’这种模式,但遇到多条件多字段时,这种就不适用了。 表字段已知,条件未知,条件数量未知,这种情况我们不可能每多一个条件就加一个and。 解决办法: 先将用户输入的条件存入一个数组中,例如以空格隔开的条件: String[] strArr = SearchText.Split(" "...

1185

C#利用S7netplus实现西门子S7_200_SMART PLC高效点位监控与操作

本文详细介绍了如何使用C#结合S7netplus开源库高效监控与操作西门子S7-200 SMART PLC的点位。内容涵盖从开发环境搭建、建立通信连接,到核心的点位读写、批量数据处理及字节与位数组转换等关键技术,并提供了构建稳定监控程序的架构与避坑指南,帮助开发者快速实现上位机与PLC的稳定数据交互。

rum55的博客 315

【Django】Django ORM Model的基本查询操作API

其中第一个元素是实例对象,第二个元素是布尔值,标识返回的实例对象是否是新创建的。由于Topic需要一个User对象,所以,先获取username是admin(超级用户)的User对象,再去创建Topic对象。它的管理器代表的是一个单一的对象,而不是对象集合,且名称变成了小写的Model名。在查询Topic的时候可能会考虑User的情况,这是很普遍的场景,也被称作跨关联查询。这样的方法返回的结果是QuerySet,所以,在它们的后面可以继续调用。关系类型也可以实现类似的反向查询,但是对于。

大河之犬的博客 1192

利用python-docx提取word的高亮部分

利用python-docx提取word的高亮部分 没有找到分享的文档,于是就自己研究了一下。 可以通过python里的python-docx去提取word内的高亮文本。 file=docx.Document(filepath) for para in file.paragraphs: for i in para.runs: #i.font.highlight_color设置了高亮颜色 if i.font.highlight_color is not None:

double_0221的博客 1810

Windows下OpenMBEE项目MMS部署失败经历及改正

在Github里找到了上面的第一份文档,下载了MMS源代码(不知道为什么这个代码跟上面操作克隆得到的MMS代码不一样?好像是因为Gradle的版本问题,我本地之前已经安装过7.6.4的Gradle了,于是我找到gradle-wrapper.properties文件。后面在VScode中运行了一下依然是报这个错误,我在VScode终端直接执行。不知道为什么依然没什么用。打开“Windows PowerShell”。(如果是第一次运行它,将看到更长的输出)导航到要克隆存储库的文件夹,例如,

Yo_lan_da的博客 1869

Django的初步理解

首先需要有数据库,采用对象关系映射器 是在models模块里面 from django.db import models class Reporter(models.Model): name = models.CharField(max_length=70) def __str__(self): return self.name Class Article(m...

king_26852的博客 131

提升YOLOv8检测精度的边界框损失函数Focaler-IoU与InnerFocalerIoU的应用与效果

YOLOv8是一种常用的实时目标检测模型,基于CNN(卷积神经网络)结构并结合了一些改进技术以提高检测精度和速度。YOLOv8的核心在于边界框的预测和分类,而准确的边界框预测是提高模型整体性能的关键因素之一。在传统的IoU损失基础上,Focaler-IoU和InnerFocalerIoU进一步聚焦于边界框的边缘区域,通过调整损失权重,更好地关注难以检测的边界框,提高模型的鲁棒性和准确性。# 计算IoU# 计算Focaler-IoU损失在这里,我们定义了。

博客 1340

django中的orm常用api总结

摘自某课网免费课程 全面掌握Django ORM # 1.查询、检索、过滤 teachers = Teacher.objects.all() print(teachers) teacher2 = Teacher.objects.get(nickname='Jack') # get()只能返回一条结果,多条则会报错 print(t...

TesuZer的博客 595

从0开始图形学(光栅化)

从0开始图形学

A112459的专栏 2395

Android 系统低内存lowmemorykiller关于阈值修改 minfreeAbsKbytes优化

在系统rom定制化开发中,在对于运行内存ram 1G和2G的设备中,对于内存使用高峰期时,minfreeAbsKbytes优化很关键 调整合理的minfree,让内存合理的使用很关键,接下来分析相关功能的实现

安卓兼职framework和app工程师的博客 524

【转】建立一个更高级别的查询 API:正确使用Django ORM 的方式

这个就比较深入啦。。。 http://www.oschina.net/translate/higher-level-query-api-django-orm 结论: 在视图和其他高级应用中使用源生的ORM查询代码不是很好的主意。而是用django-model-utils中的PassThroughManager将我们新加的自定义QuerySet API加进你的模型中,这能给你以下好处:   ...

weixin_34233618的博客 129

SwinTransformer改进(5):与CBAM结合的视觉模型

这个模型的核心思想是将Swin Transformer的强大特征提取能力与CBAM的注意力机制相结合,以提升模型对重要特征的关注度。​​CBAM模块​​:包含通道注意力和空间注意力两个子模块​​Swin Transformer主干网络​​:作为基础特征提取器​​集成结构​​:在Swin Transformer的不同阶段插入CBAM模块使用移动窗口(Moving Window)机制减少计算量层次化设计,特征图逐渐缩小,通道数逐渐增加在不同阶段使用Patch Merging进行下采样。

2401_82355416的博客 688

建立一个更高级别的查询 API:正确使用Django ORM 的方式 - 技术翻译 - 开源中国 OSChina.NET...

建立一个更高级别的查询 API:正确使用Django ORM 的方式 - 技术翻译 - 开源中国 OSChina.NET: "" (Via.) 转载于:https://www.cnblogs.com/devops/archive/2013/06/04/3117315.html

weixin_33716557的博客 104

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Python ORM(SQLAlchemy、Django ORM)的底层机制与性能优化

SQLAlchemy 和 Django ORM 都是 Python 社区中优秀的 ORM 工具,它们各自有着独特的特性和适用场景。理解它们的底层工作机制有助于更好地利用这些工具,同时合理地进行性能优化能够显著提升应用的整体表现。希望本文能为你提供有价值的参考。```

2501_90726862的博客 384

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Day49 orm 操作 Django单表操作

1、ORM简介 对象关系映射(Object Relational Mapping,简称ORM)。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。 ORM在业务逻辑层和数据库层之间充当了桥梁的作用。咱们通过一张图来介绍一下数据库与python代码之间的一个关系,请看下图: ORM的优点: 不用写繁琐的SQL语句,用咱们熟悉的pyth...

weixin_30682415的博客 163

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SQL语句和ORM框架

SQL 提供直接、高效的数据库访问,适合专家级优化;而 ORM 框架提升开发效率和安全性,适合敏捷团队。选择取决于项目需求:优先 ORM 以加速开发,在需要底层控制时使用 SQL。通过合理结合两者,可以构建健壮、可维护的数据库应用。如果您有具体场景(如特定语言或数据库),我可以提供更针对性的建议!

PGZ50588835的博客 1327

Django集成AI落地指南:从API调用到pgvector语义检索

在Web开发中,将AI能力融入现有业务系统是常见需求。Django作为成熟的开源Web框架,凭借ORM、后台管理和任务队列等内置能力,成为构建AI应用的高效基础。通过调用大模型API或使用pgvector扩展在PostgreSQL中实现语义检索,开发者无需引入额外数据库,即可为知识库问答、文档推荐等场景提供智能支持。本文从环境配置开始,逐步演示如何在Django项目中封装AI服务、实现向量检索,并探讨生产环境中的密钥管理、超时策略与异步任务等工程问题,帮助团队在开源生态下稳健落地AI功能。

weixin_30279315的博客 333

Django框架整理

Django是一个功能强大的web框架。 前言:框架模式简介 1、MVC和MTV框架模式:分层级进行管理 说到框架模式我们有必要简单的说下设计模式,了解下设计模式这个概念,因为有人对设计模式和框架模式的概念经常混淆 设计模式: 是一套被反复使用,多数人知道并经过分类的代码设计经验总结,是为了解决一些通用性问题的 目的:重用代码并保证代码的可靠性 设计模式分类:单例,抽象工厂 等等 23种模式 一句话总结:解

有用的话关个注,点个赞,收个藏🫶。 1713

Django图书管理系统全栈实战:从业务逻辑到多端扩展

在软件开发领域,构建一个完整的管理系统是检验全栈能力的重要实践。其核心在于理解并实现清晰的业务逻辑闭环,例如用户管理、资源状态流转与权限控制。从技术原理层面,这通常涉及数据模型设计、API接口规范以及前后端交互机制。其技术价值在于,通过一个典型的CRUD应用,开发者能系统掌握从数据库操作到用户界面的完整开发链路,并培养工程化思维。在实际应用场景中,此类系统常作为毕业设计或技能提升项目,尤其适合需要串联前后端技术的练习。本文以经典的“学生图书管理系统”为例,深入探讨如何基于Django框架构建一个具备完整业务

weixin_30333885的博客 371
上一篇: 基于jQuery+JSON的省市联动效果
下一篇: Django url 标签的使用
fighter_yy
博客等级 码龄20年 22粉丝 8原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值