Python除了学习基础知识之外,最常用的三大块就是数据挖掘分析
,人工智能
,Web开发
,今天就介绍下Python全栈工程师必备的知识点之一Web开发
Web框架:
别人已经设定好的一个Web网站模板,你学习它的规则,然后“填空”或“修改”成你自己需要的样子。
其它基于Python的Web框架,如Tornado、Flask、Django
都是在这个范围内进行增删裁剪的。例如Tornado
用的是自己的异步非阻塞通信协议,Flask
则只提供了最精简和基本的框架,Django
直接使用WSGI
通信协议,并实现了大部分Web应用相关的功能。
什么是WSGI?(上图黄色部分)
这里画的黄色WSGI
是统称而已,其实本身是有几个部分组合而成。
uWSGI是一个Web服务器
,它实现了WSGI协议、uwsgi、http等协议
。Nginx中HttpUwsgiModule
的作用是与uWSGI
服务器进行交换。
要注意 WSGI / uwsgi / uWSGI
这三个概念的区分。
WSGI
是一种Web服务器网关接口。它是一个Web服务器(如nginx,uWSGI等服务器)与web应用(如用Flask框架写的程序)通信的一种规范。uwsgi
是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器(Nginx)的数据通信。uWSGI
是实现了uwsgi
和WSGI
两种协议的Web服务器。图2 Web服务器架构
Nginx
通俗易懂的理解下Nginx
1.静态HTTP服务器
首先它是一个http服务器,可以将服务器上的静态文件(html,图片)通过http协议展现给客户端
2.反向代理和负载均衡
这两个特性都是相辅相成的,想象下,如果没有ng,客户端可以直接通过http协议访问某网站的应用服务器。如果加上ng,就类似ng成为了一个代理服务器,而且是反向代理服务器。(正向代理就是我们OC中写的代理,反向代理可以理解为给10086打电话)。当网站访问量大,一台服务器不够用,就会把应用部署到多台服务器上,大量用户分配给多台机器,挂一台也不影响其他。
3.反向代理和虚拟主机
有的网站访问量大就需要负载均衡。但是小公司前期没很多访问量,一台服务器也够了,会将多个网站部署到同一台服务器上。例如aaa.com和bbb.com两个网站部署在同一台服务器,两个域名解析到同一个IP,访问各自的应用网站,就像两个服务器一样,这就是所谓的虚拟主机
个人通俗的来理解下:在开始入门之前先了解下,咱们一般都是用Nginx和uWSGI进行部署我们的Django应用。首先这里客户端请求,进入Nginx,如果是静态资源,直接读取,其他转发进入uWSGI
web服务容器,首先和左侧和Nginx交互的时候实现了uwsgi
协议,右侧和Django应用交互的时候实现了WSGI
协议,这就是三个名词的基本理解了。
Python服务器类比Java
- 独立WSGI server(实现了Http服务器功能) + Python Web应用程序
- 例如:Gunicorn,uWSGI + Django,Flask
- 独立Servlet引擎(Java应用服务器)(实现了Http服务器功能) + Java Web应用程序
- 例如:Jetty,Tomcat + SpringMVC,Struts2
Python和Java服务器共同点
WSGI server(例如Gunicorn和uWSGI)
- WSGI server服务器内部都有组建来实现Socket连接的创建和管理。
- WSGI server服务器都实现了Http服务器功能,能接受Http请求,并且通过Python Web应用程序处理之后返回动态Web内容。
Java应用服务器(Jetty和Tomcat)
- Java应用服务器内部都有Connector组件来实现Socket连接的创建和管理。
- Java应用服务器都实现了Http服务器功能,能接受Http请求,并且通过Java Web应用程序处理之后返回动态Web内容。
图3 Django MTV模型组织
当一个通过上面的Ngnix
和uWSGI
转发后最后请求Django
站点的时候,下面是Django系统决定执行哪个Python代码的算法:
startproject xxx
,有个根的root conf,一般会从ROOT_URLCONF
该字段读取,但是如果有个HttpResponse对象有urlconf属性(set by middleware),这个值就会被替换掉(Django中间件全过程解析)urlpatterns
参数的,该参数是django.urls.path()
或者 django.url.re_path()
组成的列表conf
模块下是继续分发还是直接调用执行函数图1
是整体架构,图2
是对应图1WSGI
部分详细结构图,图3
是Django的MTV整体架构图。
以下就是Python的Web开发技术栈。如果一个人开发,前端这些技术必须掌握,Web服务器搞懂Nginx
和uWSGI
,公共组件按需取舍,全部用pip
进行安装,类似OC的cocoapods
,Django自带了几种ORM数据库后端,本地开发SQLIte即可,但是如果你要部署到服务器,MySQL服务器就必须掌握。
which python3
cd Desktop
mkdir Hello
virtualenv -p /usr/local/bin/python3 venv
source venv/bin/activate
# 或者 . venv/bin/activate
# deactive 关闭虚拟环境
pip install django==2.2.4
django-admin startproject mysite
mkdir templates
这里我们创建了一个主工程文件mysite
,templates如果你是用IDE启动的话默认安利给你的文件夹,也就是MVT
模型中的T。manager.py
就是项目管理脚本。
python manager runserver
可以看到启动了DJango服务器。
python manager.py startapp login
这里我们要编写稍微完整一点的Demo,用Pycharm来接管整个工程,如果你创建项目直接用Pycharm也行,但是有些你从Github下载下来的项目,你用Pycharm打开加工的话,一样需要了解一点基本的配置,不然连一点提示都没有,下面就是完整的配置。
1.模板文件提示,Pythcharm----Preference-----Language&Framework-----Python Template Languages设置成Django
,这样模板文件就有了模板提示
2.代码提示,资源跳转 Pythcharm----Preference-----Language&Framework-----Django------设置参数
3.templates
文件设置,右击----Make Directory as-----Template Folder
文件夹变成紫色,同时需要在Settings.py
中设置查找路径
4.venv
文件设置,右击----Make Directory as-----Exclusion
变成橙色
5.根目录设置,右击----Make Directory as-----SourcesRoot
变成蓝色
此时我们的项目有一个主工程mysite
,一个子工程Applogin
,首先打开mysite/urls.py
文件处理总路由入口
from django.contrib import admin
from django.urls import path, include, re_path
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^', include('login.urls', namespace='login'))
]
这里我们主工程一般不做处理,直接转发到对应的模块,比如这里转发到login
模块的urls.py
去匹配,但是我们需要在settings.py
中注册login
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login'
]
然后在login
模块中创建一个urls.py
进行匹配
from django.urls import re_path
from . import views
app_name = 'login'
urlpatterns = [
re_path(r'^index$', views.index, name='mysite_index'),
]
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello world')
上面只是简单介绍了从路由到View视图处理完的一套流程,下面接入HTML模板进行演示
首先在根目录新建一个文件夹static
,创建一个index.css
出来,然后再templates
下面新建一个index.html
。
这两个文件都需要在settings.py
中设置查找路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
修改视图返回值,用模板进行渲染
from django.shortcuts import render
def index(request):
context = {}
context['content'] = 'Hello world'
return render(request, 'index.html',context)
模板页面加载静态资源以及读取数据的方式
{% load staticfiles %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="{% static 'index.css' %}">
head>
<body>
<h1>{{ content }}h1>
body>
html>
python manage.py runserver
输入127.0.0.1:8000/index
就能看到我们的Hello World
描述一个用表单提交数据,然后展示出来的框架Demo
设计页面
# 表单页面
{% load staticfiles %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="{% static 'index.css' %}">
head>
<body>
<h1>登录h1>
<form action="{% url 'login:mysite_submit' %}" method="post">
{% csrf_token %}
用户:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="提交">
form>
body>
html>
# 结果页面
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<ul>
{% for user in lists %}
姓名:{{ user.username }}
密码:{{ user.password }}
<br>
{% endfor %}
ul>
body>
html>
模型设计
from django.db import models
class UserInfo(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
模型设计好之后,我们需要生成迁移文件以及迁移到数据库建表
python manager.py makemigrations
和 python manager.py migrate
编写路由
# 加多一条提交的路由
from django.urls import re_path
from . import views
app_name = 'login'
urlpatterns = [
re_path(r'^$', views.index, name='mysite_index'),
re_path(r'^submit$', views.submit, name='mysite_submit')
# re_path(r'^detail/(\d+)/$', views.blog_details, name='blog_details'),
]
编写View
# 处理逻辑
from django.shortcuts import render
from django.http import HttpResponse
from .models import UserInfo
def index(request):
context = {}
context['content'] = 'Hello world'
return render(request, 'index.html',context)
def submit(request):
if request.POST:
username = request.POST.get('username')
password = request.POST.get('password')
user, created = UserInfo.objects.get_or_create(username=username, password=password)
if created:
user.save()
lists = UserInfo.objects.all()
return render(request, 'result.html', context={'lists': lists })
这里写逻辑的时候我们可以进到shell
模式进行测试
python manage.py shell
>>> from login.models import UserInfo
>>> x = UserInfo.objects.all()
>>> x
<QuerySet []>
>>> str(x.query) # 查看对应的sql
'SELECT "login_userinfo"."id", "login_userinfo"."username", "login_userinfo"."password" FROM "login_userinfo"'
编写Admin显示的模型
from django.contrib import admin
from .models import UserInfo
@admin.register(UserInfo)
class UserInfoAdmin(admin.ModelAdmin):
list_display = ['pk','username','password']
创建超级管理员
python manage.py createsuperuser
随后就可以通过127.0.0.1:8000/admin
进入后台管理页面,其中能看到我们之前处理admin.py
得到的条目,可以添加或者删除数据,博客后台就这么搞定了。
启动服务
python manager.py runserver
针对这个简单的Demo,也罗列了用到的一些知识点,下面已经单独写了博客分析了
可以看到很多类似的 {% csrf_token %}
和 {% static 'index.css' %}
的东西,这个其实就是模板标签,简单理解就是左边那个是函数,有没有右侧代表函数是否带参数,很显然,static就带参数。我们来模拟一个用途
首先保证你的App被注册进入了,然后再models.py的同级目录下创建一个Python包
上面的最基本的自定义Tag,首先在模块里面必须包含一个register的模块级变量,才可以通过装饰器注册tag标签,使用如下
{% load login_tags %}
......
<h1>登录{% get_comment_count '1000' %}h1>
......
CSRF
装饰器和偏函数
六大模块之ContentType App
中间件
SQLIte迁移成Mysql
静态资源开发配置和部署搜集
总结:上面介绍了Django Web开发最基本的框架,开发阶段静态资源不需要单独处理,只需要指定路径即可,部署的时候我们会通过脚本把静态资源搜集到一个目录下,配置给到Nginx进行管理。开发阶段的数据库可以用SQLIte进行,不需要单独的其他配置,等到部署之前,需要按上面的教程迁移到Mysql,其中涉及到一些坑已经有详细介绍,跟着做就好了,特别注意Mysql的字符编码集和校对规则就好了,不然数据不兼容是最难受的。本地部署前准备后就需要买个服务器进行部署了,时间不多,下次在详述如何用Nginx和uWSGI部署到Center OS服务器。
以下是空余时间陆陆续续写的博客框架,放在Github了,有兴趣的可以研究下传送门