1. 请对比说明Django,Flask,Tornado
- 要点
1. Django:是一个功能强大的高级 Web 框架,遵循 MVC(实际上是 MTV)架构模式。它内置了丰富的功能,如 ORM(对象关系映射),管理界面,表单处理,认证系统等,适合快速开发大型,复杂的 Web 应用。
python
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
def __str__(self):
return self.title
# 在视图中使用 ORM 查询数据
from .models import Book
def get_books(request):
books = Book.objects.all()
return books
2. Flask:是一个轻量级的 Web 框架,被称为 “微框架”。它只提供了 Web 开发的核心功能,如路由,请求处理等,开发者可以根据需要选择合适的扩展来实现更多功能,灵活性高,适合小型项目和快速原型开发。
python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
3. Tornado:是一个高性能的 Python Web 框架和异步网络库,它采用异步 I/O 和非阻塞 I/O 技术,能够处理大量并发连接,适合开发实时性要求高,高并发的 Web 应用,如在线游戏,实时聊天等。
python
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
- 性能
-
Django:由于其功能丰富,包含了很多内置组件,相对来说性能开销较大。在处理高并发请求时,可能需要借助其他技术(如缓存、异步任务队列)来提高性能。
-
Flask:轻量级的特点使得它的性能开销较小,在处理简单请求时速度较快。但如果不进行优化,在高并发场景下也会面临性能瓶颈。
-
Tornado:采用异步 I/O 和非阻塞 I/O 技术,能够高效地处理大量并发连接,性能表现优秀,尤其在高并发场景下优势明显。
- 学习曲线
-
Django:由于其功能复杂,学习曲线较陡,需要掌握较多的概念和技术,如 ORM,模板系统,管理界面等。
-
Flask:简单易学,只需要掌握基本的路由和请求处理知识,就可以快速上手开发 Web 应用。
-
Tornado:异步编程的概念相对较难理解,学习曲线也比较陡,需要掌握异步 I/O,协程等知识。
2. 说明CORS 和 CSRF 的区别
- 要点
-
CORS(跨域资源共享):是一种机制,它允许浏览器向跨源服务器发送请求,克服了浏览器的同源策略限制。同源策略要求浏览器只能访问同源(协议、域名、端口都相同)的资源,CORS 通过在服务器端设置响应头来允许跨源请求。
python
# Flask 中设置 CORS 示例
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route('/')
def hello():
return 'Hello from cross - origin!'
if __name__ == '__main__':
app.run()
2. CSRF(跨站请求伪造):是一种攻击方式,攻击者通过诱导用户在已登录的网站上执行恶意操作,利用用户的身份信息向目标网站发送伪造的请求。
python
# Django 视图中使用 CSRF 保护
from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def my_view(request):
return render(request, 'my_template.html')
- 防护机制
-
CORS:主要通过服务器端设置响应头(如
Access-Control-Allow-Origin)来控制哪些源可以访问资源。 -
CSRF:常见的防护措施包括使用 CSRF 令牌、验证请求来源、设置 SameSite 属性等。
3. 说明Session、Cookie、JWT 的功能特性
- Session
-
概念:是一种服务器端的会话机制,用于跟踪用户的会话状态。服务器为每个用户创建一个唯一的会话 ID,并将其存储在 Cookie 中发送给客户端。客户端每次请求时都会携带该会话 ID,服务器根据会话 ID 来识别用户。
-
优点:数据存储在服务器端,安全性较高;可以存储复杂的数据类型。
-
缺点:需要服务器端存储会话数据,增加了服务器的负担;在分布式系统中需要处理会话共享问题。
python
# Flask 中使用 Session 示例
from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'your_secret_key'
@app.route('/set_session')
def set_session():
session['username'] = 'test_user'
return 'Session set'
@app.route('/get_session')
def get_session():
username = session.get('username')
return f'Username in session: {username}'
if __name__ == '__main__':
app.run()
Cookie
-
概念:是一种客户端的会话机制,用于在客户端和服务器之间传递少量数据。服务器可以在响应头中设置 Cookie,客户端会将其存储在本地。客户端每次请求时都会携带这些 Cookie,服务器可以根据 Cookie 中的信息来识别用户。
-
优点:实现简单,不需要服务器端存储数据;可以在不同页面之间共享数据。
-
缺点:数据存储在客户端,安全性较低;存储容量有限。
python
# Flask 中设置和获取 Cookie 示例
from flask import Flask, make_response, request
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
resp = make_response('Cookie set')
resp.set_cookie('username', 'test_user')
return resp
@app.route('/get_cookie')
def get_cookie():
username = request.cookies.get('username')
return f'Username in cookie: {username}'
if __name__ == '__main__':
app.run()
- JWT(JSON Web Token)
-
概念:是一种用于在网络应用中安全传输信息的开放标准(RFC 7519)。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。JWT 通常用于身份验证和授权,服务器在用户登录成功后生成一个 JWT 并返回给客户端,客户端每次请求时都会携带该 JWT,服务器通过验证 JWT 的签名来确认请求的合法性。
-
优点:无状态,不需要服务器端存储会话数据,适合分布式系统;可以在不同的服务之间共享用户信息。
-
缺点:JWT 的载荷部分是明文的,不能存储敏感信息;JWT 的签名一旦被破解,安全性将受到威胁。
python
import jwt
from datetime import datetime, timedelta
# 生成 JWT
def generate_token(user_id):
payload = {
'user_id': user_id,
'exp': datetime.utcnow() + timedelta(hours=1)
}
token = jwt.encode(payload, 'your_secret_key', algorithm='HS256')
return token
# 验证 JWT
def verify_token(token):
try:
payload = jwt.decode(token, 'your_secret_key', algorithms=['HS256'])
return payload
except jwt.ExpiredSignatureError:
return None
except jwt.InvalidTokenError:
return None
4. 简述 Django请求的生命周期
-
客户端发起请求:用户在浏览器中输入 URL 或点击链接,向服务器发送 HTTP 请求。
-
Web 服务器接收请求:Web 服务器(如 Nginx、Apache)接收到请求后,将其转发给 Django 应用。
-
中间件处理:Django 应用首先会经过一系列中间件的处理,中间件可以对请求进行预处理(如身份验证、日志记录)和后处理(如设置响应头)。
python
# 自定义 Django 中间件示例
class CustomMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 预处理
print('Before view')
response = self.get_response(request)
# 后处理
print('After view')
return response
4. URL 路由:Django 根据请求的 URL,在urls.py文件中查找匹配的 URL 模式,并将请求分发到对应的视图函数或类视图。
python
# urls.py
from django.urls import path
from .views import my_view
urlpatterns = [
path('my_url/', my_view, name='my_view'),
]
5. 视图处理:视图函数或类视图接收到请求后,进行业务逻辑处理,可能会访问数据库、调用其他服务等。
python
# views.py
from django.http import HttpResponse
def my_view(request):
return HttpResponse('Hello from view!')
6. 模板渲染(可选):如果视图需要返回 HTML 页面,会使用 Django 的模板系统将数据和模板文件进行渲染,生成 HTML 内容。
python
# views.py
from django.shortcuts import render
def my_template_view(request):
context = {'message': 'Hello from template!'}
return render(request, 'my_template.html', context)
7. 响应处理:视图处理完请求后,会返回一个 HTTP 响应对象。响应对象包含了响应状态码、响应头和响应体等信息。
8. 中间件后处理:响应对象会再次经过中间件的处理,中间件可以对响应进行后处理(如压缩响应内容、设置缓存头)。
9. Web 服务器返回响应:Web 服务器将处理后的响应返回给客户端,客户端浏览器接收到响应后进行渲染和显示。
5. 用 Django REST framework 完成 API 发送时间时区
使用 Django REST framework 创建一个 API,返回当前时间并包含时区信息:
python
# models.py
from django.db import models
class TimeZone(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
# serializers.py
from rest_framework import serializers
import pytz
from django.utils import timezone
class TimeZoneSerializer(serializers.Serializer):
timezone = serializers.CharField()
current_time = serializers.SerializerMethodField()
def get_current_time(self, obj):
tz = pytz.timezone(obj['timezone'])
current_time = timezone.now().astimezone(tz)
return current_time.strftime('%Y-%m-%d %H:%M:%S %Z')
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import TimeZoneSerializer
import pytz
class TimeZoneAPIView(APIView):
def get(self, request):
timezone_name = request.query_params.get('timezone', 'UTC')
try:
pytz.timezone(timezone_name)
except pytz.UnknownTimeZoneError:
return Response({'error': 'Invalid timezone'}, status=400)
data = {'timezone': timezone_name}
serializer = TimeZoneSerializer(data)
return Response(serializer.data)
# urls.py
from django.urls import path
from .views import TimeZoneAPIView
urlpatterns = [
path('timezone/', TimeZoneAPIView.as_view(), name='timezone-api'),
]
6. 说明Nginx,Tomcat,Apache 的功能特性
- Nginx
-
简介:是一个高性能的 HTTP 服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。它以事件驱动的方式处理请求,具有高并发、低内存占用的特点,常用于负载均衡、静态资源服务、反向代理等场景。
-
应用场景:作为 Web 服务器提供静态资源服务;作为反向代理服务器,将请求转发到后端的应用服务器;实现负载均衡,将请求均匀地分配到多个后端服务器上。
nginx
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X - Real - IP $remote_addr;
}
}
- Tomcat
-
简介:是一个开源的 Servlet 容器,用于运行 Java Web 应用。它实现了 Servlet 和 JSP 规范,能够处理动态请求,将 Java 代码转换为 HTML 页面返回给客户端。
-
应用场景:主要用于运行基于 Java 的 Web 应用,如 JavaEE 项目、Spring Boot 项目等。
- Apache
-
简介:是一个开源的 HTTP 服务器软件,功能强大,支持多种模块和插件。它以进程或线程的方式处理请求,具有良好的稳定性和兼容性,常用于静态资源服务、动态内容生成等场景。
-
应用场景:作为 Web 服务器提供静态资源服务;通过加载不同的模块(如 mod_php)来处理动态请求,支持多种编程语言(如 PHP、Python 等)。
apache
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
AddHandler application/x - httpd - php .php
PHPIniDir /etc/php
</VirtualHost>
7. 常见关系数据库范式有哪些,有什么作用?
- 第一范式(1NF)
-
定义:数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。例如,一个学生表中,“联系方式” 列不能同时包含多个电话号码,应拆分为多个列。
-
作用:确保数据的原子性,使数据结构更加清晰,便于数据的存储和管理。
- 第二范式(2NF)
-
定义:在满足第一范式的基础上,非主属性完全依赖于主键,而不是部分依赖于主键。例如,一个订单表,主键是(订单号,商品编号),“商品价格” 只依赖于 “商品编号”,这就存在部分依赖,应将 “商品价格” 移到商品表中。
-
作用:消除部分依赖,减少数据冗余,提高数据的一致性和完整性。
- 第三范式(3NF)
-
定义:在满足第二范式的基础上,非主属性之间不存在传递依赖,即非主属性不能依赖于其他非主属性。例如,一个员工表,“部门编号” 决定 “部门地址”,“员工编号” 决定 “部门编号”,存在传递依赖,应将 “部门地址” 移到部门表中。
-
作用:消除传递依赖,进一步减少数据冗余,提高数据的更新效率和数据的一致性。
- 巴斯 - 科德范式(BCNF)
-
定义:在满足第三范式的基础上,每一个非平凡的函数依赖的左边必须包含候选键。例如,一个关系表中存在函数依赖
A -> B,B -> C,若B不是候选键,则不满足 BCNF,需要进行分解。 -
作用:解决了第三范式中可能存在的主属性对候选键的部分和传递依赖问题,进一步提高了数据的规范性和一致性。
8. 简述 QQ 登陆过程
-
客户端请求授权:用户在第三方应用中点击 QQ 登录按钮,第三方应用将用户重定向到 QQ 的授权页面,同时携带第三方应用的 ID、回调 URL 等信息。
-
用户登录 QQ:用户在 QQ 授权页面输入 QQ 账号和密码进行登录。
-
用户授权:登录成功后,QQ 会提示用户确认是否授权第三方应用访问其信息。用户点击确认授权后,QQ 会生成一个授权码。
-
获取授权码:QQ 将授权码通过回调 URL 返回给第三方应用。
-
换取访问令牌:第三方应用使用授权码向 QQ 的授权服务器发送请求,换取访问令牌(Access Token)。
python
import requests
# 假设以下是获取访问令牌的示例代码
def get_access_token(authorization_code):
url = 'https://graph.qq.com/oauth2.0/token'
params = {
'grant_type': 'authorization_code',
'client_id': 'your_client_id',
'client_secret': 'your_client_secret',
'code': authorization_code,
'redirect_uri': 'your_redirect_uri'
}
response = requests.get(url, params=params)
return response.json()
6. 获取用户信息:第三方应用使用访问令牌向 QQ 的用户信息接口发送请求,获取用户的基本信息(如昵称、头像、性别等)。
python
def get_user_info(access_token, openid):
url = 'https://graph.qq.com/user/get_user_info'
params = {
'access_token': access_token,
'oauth_consumer_key': 'your_client_id',
'openid': openid
}
response = requests.get(url, params=params)
return response.json()
7. 登录第三方应用:第三方应用根据获取到的用户信息,为用户创建或查找对应的账号,并完成登录流程。
9. 说明POST 和 GET 的区别
- 要点
-
GET:通常用于获取资源,请求参数会附加在 URL 后面,如
http://example.com/api?param1=v alue1¶m2=value2。
python
import requests
url = 'http://example.com/api'
params = {'param1': 'value1', 'param2': 'value2'}
response = requests.get(url, params=params)
2. POST:通常用于提交数据,请求参数会放在请求体中,不会显示在 URL 中。
python
import requests
url = 'http://example.com/api'
data = {'param1': 'value1', 'param2': 'value2'}
response = requests.post(url, json=data)
- 安全性
-
GET:请求参数会暴露在 URL 中,不安全,不适合传输敏感信息。
-
POST:请求参数放在请求体中,相对安全,适合传输敏感信息。
- 数据长度
-
GET:URL 的长度有限制,因此 GET 请求所能携带的参数长度也有限制。
-
POST:请求体的长度没有限制,可以传输大量的数据。
- 缓存
-
GET:请求可以被缓存,浏览器会根据缓存策略决定是否使用缓存数据。
-
POST:请求通常不会被缓存。
10. 说明项目中日志的作用
-
调试和排错:在开发和测试阶段,日志可以记录程序的运行状态、变量的值、函数的调用顺序等信息,帮助开发人员快速定位和解决问题。
- 这里使用
logging模块记录日志。通过设置日志级别为DEBUG,可以记录详细的调试信息。 - 在
divide_numbers函数中,开始时记录了传入的参数,运算成功时记录结果,发生异常时记录错误信息并打印堆栈跟踪,方便开发者快速定位问题。
python
import logging
# 配置日志
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def divide_numbers(a, b):
logging.debug(f"开始执行 divide_numbers 函数,参数 a={a}, b={b}")
try:
result = a / b
logging.debug(f"除法运算成功,结果为 {result}")
return result
except ZeroDivisionError:
logging.error("除数不能为零", exc_info=True)
return None
# 调用函数
divide_numbers(10, 0)
-
监控和分析:在生产环境中,日志可以记录系统的运行情况、用户的操作行为、错误信息等,帮助运维人员监控系统的性能和稳定性,分析用户行为和业务数据。
- 日志级别设置为
INFO,记录用户登录和退出系统的操作信息。 - 通过分析这些日志信息,运维人员可以了解用户的使用习惯、系统的访问频率等,有助于优化系统性能和改进业务流程。
python
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def user_login(user_id):
logging.info(f"用户 {user_id} 登录系统")
def user_logout(user_id):
logging.info(f"用户 {user_id} 退出系统")
# 模拟用户操作
user_login("user123")
# 模拟一些业务操作
user_logout("user123")
-
安全审计:日志可以记录用户的登录信息、权限变更、敏感操作等,用于安全审计和合规性检查。
- 日志级别设置为
WARNING,用于记录敏感的权限变更操作。 - 在安全审计时,可以通过查看这些日志,确保所有的权限变更都是经过授权的,防止非法操作。
python
import logging
# 配置日志
logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(levelname)s - %(message)s')
def change_user_permission(user_id, new_permission):
logging.warning(f"用户 {user_id} 的权限变更为 {new_permission}")
# 模拟权限变更操作
change_user_permission("admin", "super_admin")
-
性能优化:通过分析日志中的性能指标(如响应时间、吞吐量等),可以找出系统的性能瓶颈,进行优化和改进。
- 在函数开始和结束时分别记录时间,计算函数的执行时间并记录日志。
- 通过分析这些性能相关的日志信息,可以找出执行时间过长的函数或操作,进而进行优化,提高系统的整体性能。
python
import logging
import time
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def long_running_task():
start_time = time.time()
# 模拟一个耗时操作
time.sleep(2)
end_time = time.time()
execution_time = end_time - start_time
logging.info(f"long_running_task 函数执行时间: {execution_time} 秒")
# 调用耗时操作函数
long_running_task()
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读

811

被折叠的 条评论
为什么被折叠?



