操作系统:windows
IDE:Pycharm
读取数据库数据:
现在已经有了数据库和定义好的Customer表,也在表中添加了两条数据信息。
现在需要实现一个功能:前端浏览器访问 sales/customers/
这个URL,后端服务端就返回用户的记录给浏览器。
首先需要实现一个函数,来处理浏览器发出的URL为 sales/customers/
的访问请求,我们需要返回数据库中customer表中的所有记录。
Django 中对数据库表的操作, 应该都通过 Model对象 实现对数据的读写,而不是通过SQL语句。
需要获取customer表所有记录, 该表是由之前定义的 Customer类进行操作的。
获取所有的表记录:
在文件sales/views.py 中,定义一个listcustomers
函数,内容如下:
# 导入 Customer 对象定义
from common.models import Customer
# 列出客户信息
def listcustomers(request):
# values()方法返回一个QuerySet对象,包含所有的表记录
# 每条表记录都是是一个dict对象,
# key是字段名,value是字段值
# objects是Customer的父类Model用来操作数据库的Manage接口,由Django定义
qs = Customer.objects.values()
# 定义返回字符串
retStr = ''
for customer in qs:
for name, value in customer.items():
retStr += f'{name} : {value} | '
# <br> 表示换行
retStr += '<br>'
return HttpResponse(retStr)
QuerySet
对象 可以使用 for 循环遍历取出里面所有的元素,每个元素对应一条表记录。每条表记录元素都是一个dict对象,其中 每个元素的key是表字段名,value是该记录的字段值。
然后还要在 sales/urls 二级路由表中添加上对应的路由信息:
from django.urls import path
from sales.views import listorders, listcustomers
urlpatterns = [
path('orders/', listorders),
path('customers/', listcustomers)
]
运行之后,用浏览器访问127.0.0.1:8080/sales/customers
可以看到效果:
可以看到字符串作为html被浏览器解析,<br>
实现了换行。简单实现了数据库中的信息被放到前端。
添加过滤条件:
有的时候,我们需要根据过滤条件查询部分客户信息。
比如,当用户在浏览器输入 /sales/customers/?phonenumber=150646442864
,要求返回电话号码为 150646442864 客户记录。
我们可以通过filter方法加入过滤条件,修改view里面的代码,如下所示:
# 列出客户信息
def listcustomers(request):
# values()方法返回一个QuerySet对象,包含所有的表记录
# 每条表记录都是是一个dict对象,
# key是字段名,value是字段值
# objects是Customer的父类Model用来操作数据库的Manage接口,由Django定义
qs = Customer.objects.values()
# 检查url中是否有phonenumber
# 从request对象的GET请求中,找key值:phonenumber, 如果没有就是None,操作有点像字典dict
ph = request.GET.get('phonenumber', None)
if ph:
qs = qs.filter(phonenumber=ph)
# 定义返回字符串
retStr = ''
for customer in qs:
for name, value in customer.items():
retStr += f'{name} : {value} | '
# <br> 表示换行
retStr += '<br>'
return HttpResponse(retStr)
Django框架在url路由匹配到函数后, 调用函数时,会传入一个HttpRequest
对象给参数变量 request
,该对象里面包含了请求的数据信息。
HTTP 的 Get 请求url里面的参数(术语叫 querystring
里面的参数),可以通过 HttpRequest
对象的 GET 属性获取。这是一个类似dict的对象。
例如一个url:/users/?id=123&tel=15050
,执行到request.GET时,会把所有参数取出来放到一个字典当中:
request.GET = {
'id':'123',
'tel':'15050'
}
然后通过调用 QuerySet 对象的filter方法,就可以把查询过滤条件加上去
qs = qs.filter(phonenumber=ph)
有了这个过滤条件,Django会在底层执行数据库查询的SQL语句加上相应的 where从句,进行过滤查询。
注:
- 参数名
phonenumber
是和定义的表 model的属性名phonenumber
一致的。 - filter的过滤条件可以有多个,只要继续在后面的参数添加过滤条件即可。
打开浏览器,访问127.0.0.1:8080/sales/customers/?phonenumber=150646442864
可以看到过滤条件生效了
使用模板来生成HTML:
上面的相当于简单的把数据放在网页上,如果要用一个表格来显示数据,该怎么做呢?
HTML其实也是一个字符串,可以用循环加上标签,拼接字符串来生成HTML,但这显然不是一个好方法。
很多后端框架都提供了一种模板技术, 可以在HTML中嵌入编程语言代码片段, 用模板引擎(就是一个专门处理HTML模板的库)来动态的生成HTML代码。
比如JavaEE 里面的JSP。
Python 中有很多这样的模板引擎 比如 jinja2 、Mako, Django也内置了一个这样的模板引擎。
现在使用Django的模板引擎,来构建出 HTML 字符串内容:
还是在sales/views.py中:
# 先定义好HTML模板
html_template = '''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
table {
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
</style>
</head>
<body>
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>电话号码</th>
<th>地址</th>
</tr>
<!-- customers就是从数据库中读出来的QuerySet对象 -->
{% for customer in customers %}
<tr>
{% for name, value in customer.items %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</body>
</html>
'''
# engines就是Django自带的的模板引擎
# template这里就是模板对象
from django.template import engines
django_engine = engines['django']
template = django_engine.from_string(html_template)
def listcustomers(request):
# 返回一个 QuerySet 对象 ,包含所有的表记录
qs = Customer.objects.values()
# 检查url中是否有参数phonenumber
ph = request.GET.get('phonenumber',None)
# 如果有,添加过滤条件
if ph:
qs = qs.filter(phonenumber=ph)
# 传入渲染模板需要的参数,把qs传入模板中的customers
rendered = template.render({'customers': qs})
return HttpResponse(rendered)
模板的效果如图,如果用模板实现更好的效果可以考虑了解一下bootstrap
前后端分离架构:
有了模板引擎,对我们后端开发来说,简化了程序员后端生成HTML的任务,提高了开发效率。但是实际生产过程中,基本都是前后端分离的架构。
不使用前后端分离,有什么弊端?
- 前后端开发人员要做额外的沟通。
- 如果前端除了web浏览器,还有手机APP的话, APP 不需要服务端返回HTML, 就得再开发一套数据接口
- 渲染任务在后端执行,大大的增加了后端的性能压力(render很吃CPU)。尤其是有的HTML页面很大, 当有大量的用户并发访问的时候, 后端渲染工作量很大,很耗费CPU 资源。
现在随着浏览器中javascript 解释器性能的突飞猛进,以及一些前端模板库和框架的流行。很多架构师将页面的html内容生成 的任务放到前端。
这样服务端就只负责提供数据, 界面的构成全部在前端(浏览器前端或者手机前端)进行,称之为前端渲染。这个工作在前端执行, 使用前端的框架库去完成,比如 Angular,React,Vue。
这样界面完全交给前端开发人员去做, 后端开发只需要提供前端界面所需要的数据就行了。
前端和后端之间的交互就完全是业务数据了。
这样需要定义好前端和后端交互数据的接口。
目前通常这样的接口设计最普遍的就是使用 REST 风格的 API 接口。
- 前端通过API 接口从后端获取数据展示在界面上。
- 前端通过API 接口告诉后端需要更新的数据是什么。
通常前后端的 API 接口是由架构师设计的, 有时也可以由经验丰富的前端开发者、或者后端开发者设计。后端开发人员只需要根据这个接口文档,实现后端系统的部分。
注意:需要Django返回的信息,通常都是所谓的动态数据信息。 比如:用户信息,订单信息,等等这些信息通常都是存在数据库中,这些信息是会随着系统的使用发生变化的。
而静态信息,比如: 页面HTML文档、css文档、图片、视频等,是不应该由 Django 负责返回数据的。
这些数据通常都是由其他静态资源服务软件,比如 Nginx、Varnish等等,返回给前端。这些软件都会有效的对静态数据进行缓存,大大提高服务效率。在实际的项目中,往往还会直接使用静态文件云服务( OSS + CDN )提供静态数据的访问服务。
总之,Django处理并返回的应该是动态业务数据信息。