埋头工作
专职养娃

django框架admin后台配置系列之二:admin后台美化插件推荐

xinyigirl阅读(1131)

admin后台功能强大,但是你的会用啊

我们都知道django自带的admin虽然是开箱即用,但是你过时的页面配色和布局在现在人的审美下,显得有点“丑陋”,既然admin后台有着内在的气质,那么我们也要给予其漂亮的外表才行。那么直接美化后台的话,目前主流的方式是采用第三方插件库来进行快速实现

自带admin后台的目的是为了让系统管理员有一个比较直观和便捷的方式来直接维护数据,其定位不是为了面向最终用户
如果你想做一款面向最终普通用户的web页面,请采用DTL或者其他前端框架全自定义打造
主流的方案有引入bootstrap模板结合DTL进行修改;使用VUE或者其他前后端分离的web框架搭建

1、插件1:django-simpleui

官网
目前业界最流行的开源admin后台插件,全星推荐,理由如下

  • 优点:
    • 开箱即用
    • 页面美观,国人审美标准,采用element-ui+vue开发
    • 主题可变
    • 自定义能力强
  • 缺点:
    • 配置麻烦,因为自定义能力强,如果使用其自定义能力,那么就需要详细阅读官网文档
    • 免费版和付费版本差别巨大,其实有兴趣的完全可以用免费版加其他图形化插件进行扩展
      file
      你可以查看在线demo看下效果
      demo
      但是用户可以完全开箱即用,不用哪些个性化的配置能力

2、插件2:django-xadmin

这个目前基本已经停止维护了,是采用bootstrap3样式来打造的,在django2.0的时代,几乎是django admin后台美化的霸主,如果使用django3.0及以上的话,就别用了。

file

3、插件3:django-suit

这个是国外开发的插件,相比原生admin主要做了两个改变

  • 增加侧边栏
  • 将右侧的过滤转换到表格最上方
    file

    非商业用途,免费,商业用途收费

4、插件4:Django-grappelli

也是国外开发的插件,风格简单干净,全免费,但是样式个人觉得过时了。
file

写在最后,国人使用的话,只推荐django-simpleui,没有其他。

django框架admin后台配置系列之一:各类操作目录

xinyigirl阅读(813)

前言

django为了方便快速对数据库进行管理,或者快速搭建一个可用的web系统,内置了admin后台能力,用户可以通过ModelAdmin类提供的配置能力,快速实现一个web后台的创建,提供了一个快速的, 以模型为中心的web界面。
针对admin这块的管理,可以参见每一个版本的“管理站点”,比如3.1版本的如下
https://docs.djangoproject.com/zh-hans/3.1/

一、基础准备

在setting中要进行基础配置。

  1. django项目创建好之后,setting中会默认把django相关需要配置的内容进行预配置,主要包括下面的部分。
    • ‘django.contrib.admin’ 和它的依赖关系 —— django.contrib.auth、django.contrib.contenttypes、django.contrib.messagesdjango.contrib.session 添加到你的 INSTALLED_APPS 配置中。
    • 在你的 TEMPLATES 配置中设置一个在 OPTIONS 的 ‘context_processors’ 选项中包含 django.template.context_processors.request、django.contrib.auth.context_processors.auth 和 django.contrib.messages.context_processors.messages 的 DjangoTemplates 后端:
    • 如果你自定义了 MIDDLEWARE 设置,则必须包含 django.contrib.auth.middleware.AuthenticationMiddleware 和 django.contrib.messages.middleware.MessageMiddleware。
    • 把管理的网址挂到你的 URLconf 里。
  2. 我们自己需要在setting中做哪些改变呢?
    • 加入你自己对系统默认的User类进行了额外的继承扩展或者完全重新自己写了一个类,那么就需要在setting中将用户管理设置为自定义的类,配置的方法是:AUTH_USER_MODEL = ‘myapp.MyUser’

      格式是app名字.model名字

二、admin自定义分类

1、区域划分

在admin后台的管理中,我们所看到的页面视图个人觉得可以将其分为几个区域

  • admin总体信息:网站名字等
  • 菜单区域
  • list页面的按钮区域
  • list页面的内容区域
  • 对象表单

2、操作分类

结合上面四个区域页面,我个人按照我所碰到的各种需要进行扩展或者修订的类型,将其分为下面的几大类的自定义入口类型:

  1. 后台管理总体信息修改

  2. list页面的按钮区域

    • 对list区域增删按钮
    • 对list区域搜索框和下拉框进行增删
  3. 对list页面的内容区域

    • 对list区域增删显示字段
    • 对list区域字段超链接修改
      file
  4. 对象表单

    • 按钮位置修改
    • 按钮增删
    • 表单的布局
    • 新增时表单显示
    • 修改时表单显示
      file
  5. 权限关联:根据权限对2&3&4三部分进行个性化区分显示

    • 我们在实际的生产中要实现对权限的自定义的话,其实可以将上面的各种信息都进行模型抽象,然后结合一整套完善的基础权限管理能力进行统一扩展。

后面的系列文章也将从操作分类分别进行总结。

Django出现“Too many connections”错误

xinyigirl阅读(883)

一、错误原因

这个错误是mysql数据库上报的,django的ORM在进行数据库连接时,数据库连接数超过阈值,导致各种请求都会失败,具体的效果会是

  1. 所有的请求都会是500错误
  2. django内置admin页面打开也显示too many connections错误
  3. 归根结底就是django的数据库连接配置和mysql的配置配合的问题

二、初步排查

一般普通的django项目的连接数很难会出现这种问题,如果真的出现问题,最大的可能性就是你的django项目代码存在缺陷,比如,明明你可以进行批量操作的语句,非要做单条执行;又或者你在每一个请求开始的时候都进行了大量的update操作等等。我们可以按照下面的方式进行排查

1、登录mysql数据库查看连接情况 show processlist;

show processlist;

查看哪些连接时间过长,并且info语句的内容基本相同,通过sql语句反向推测出django的ORM语句,定位到具体的代码段进行优化。

2、登录mysql查看mysql数据库的最大连接数

  • 查看mysql数据库配置连接数 max_connections
    mysql> show variables like '%conn%';
    +-----------------------------------------------+--------------------+
    | Variable_name                                 | Value              |
    +-----------------------------------------------+--------------------+
    | character_set_connection                      | utf8mb4            |
    | collation_connection                          | utf8mb4_0900_ai_ci |
    | connect_timeout                               | 10                 |
    | disconnect_on_expired_password                | ON                 |
    | init_connect                                  |                    |
    | max_connect_errors                            | 100                |
    | max_connections                               | 500                |
    | max_user_connections                          | 0                  |
    | mysqlx_connect_timeout                        | 30                 |
    | mysqlx_max_connections                        | 100                |
    | performance_schema_session_connect_attrs_size | 512                |
    +-----------------------------------------------+--------------------+
    11 rows in set (0.11 sec)
  • 查看使用数
    mysql> show global status like '%conn%';
    +-------------------------------------------------------+---------------------+
    | Variable_name                                         | Value               |
    +-------------------------------------------------------+---------------------+
    | Aborted_connects                                      | 0                   |
    | Connection_errors_accept                              | 0                   |
    | Connection_errors_internal                            | 0                   |
    | Connection_errors_max_connections                     | 0                   |
    | Connection_errors_peer_address                        | 0                   |
    | Connection_errors_select                              | 0                   |
    | Connection_errors_tcpwrap                             | 0                   |
    | Connections                                           | 915                 |
    | Locked_connects                                       | 0                   |
    | Max_used_connections                                  | 73                  |
    | Max_used_connections_time                             | 2022-07-11 10:14:36 |
    | Mysqlx_connection_accept_errors                       | 0                   |
    | Mysqlx_connection_errors                              | 0                   |
    | Mysqlx_connections_accepted                           | 0                   |
    | Mysqlx_connections_closed                             | 0                   |
    | Mysqlx_connections_rejected                           | 0                   |
    | Performance_schema_session_connect_attrs_longest_seen | 126                 |
    | Performance_schema_session_connect_attrs_lost         | 0                   |
    | Ssl_client_connects                                   | 0                   |
    | Ssl_connect_renegotiates                              | 0                   |
    | Ssl_finished_connects                                 | 0                   |
    | Threads_connected                                     | 32                  |
    +-------------------------------------------------------+---------------------+
    22 rows in set (0.15 sec)

    三、优化处理

    1、优化代码

    将django定位到的代码段进行ORM操作优化,将for循环类的操作全都改成批量操作

    2、修改mysql配置文件

  • 临时修改,具体数值自己根据服务器的性能决定,数据库重启后失效
    set GLOBAL max_connections=1000; # 总的最大连接数
    set GLOBAL max_user_connections=500; # 每个账号最大的连接数
    set GLOBAL wait_timeout=500; # 最大空闲时间,会强制释放sleep的链接
    set GLOBAL interactive_timeout=500; # 最大检测时间
  • 永久修改,修改配置文件
    • 查看配置文件路径ps aux|grep mysql|grep ‘my.cnf’ 和 mysql –help|grep ‘my.cnf’
    • 修改配置文件
    • 重启mysql服务
      //查看配置文件的路径
      [root@api etc]# ps aux|grep mysql|grep 'my.cnf'
      //如果没有输出,就查看默认路径配置
      [root@api etc]# mysql --help|grep 'my.cnf' 
                    order of preference, my.cnf, $MYSQL_TCP_PORT,
      /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 
      [root@api etc]# vi /etc/my.cnf
      //在[mysqld]下增加配置
      max_connections=500
      max_user_connections=500
      wait_timeout=600
      interactive_timeout=600
      //保存,重启
      [root@api etc]systemctl restart mysqld
      [root@api etc]systemctl status mysqld

      3、django数据库配置和mysql配合

      django的数据库配置中除了数据库连接的信息之外,还提供了一个额外的参数——"CONN_MAX_AGE"

      默认: 0
      一个数据库连接的寿命,以秒为整数。使用 0 在每次请求结束时关闭数据库连接——这是 Django 的历史行为,使用 None 则是无限的持久连接。
      链接

通俗讲就是一个django和mysql的连接的最大空闲时间,那么对应数据库中的配置就是 wait_timeout 和 interactive_timeout两个参数。

正确的值配置方式应该是
wait_timeout>=interactive_timeout>django中的CON_MAX_AGE

4、修改django的最大连接数配置(其他论坛帖子的解释,没有把问题将清楚,可以参考一下)

在数据库中,有一个参数 CONN_MAX_AGE , 它用来配置 Django 跟数据库的持久化连接。这一项的默认值是0。 Django 中数据库连接的逻辑是,每一个请求结束都会关闭当前的数据库连接。这意味着每来一个新的请求, Django 都会创建一个新的数据库连接。

当配置此项的值时,需要根据参考数据库的 wait_timeout 配置,建议不要大于 wait_timeout 。此外此项还有 None。如果配置为 None,就意味着不限制连接时长。

如果没有配置 CONN_MAX_AGE 就会出现数据库连接数太多,抛出 too many connections 错误的问题,原因就是上面所说的,所以当并发访问量过大来不及关闭连接时,会导致连接数不断增多。

但是需要注意的是,如果你采用多线程的方式部署项目,最好不要配置 CONN_MAX_AGE。因为如果每一个请求都会使用一个新的线程来处理的,那么每个持久化的连接就达不到复用的目的。另外一个经验就是,如果使用gevent 作为worker来运行项目的话,那么也建议不配置 CONN_MAX_AGE。因为 gevent 会给 Python 的 thread(线程模块)动态打补丁(patch),这回导致数据库连接无法复用

此段参考《Django 项目部署上线后,数据库连接数太多,抛出too many connections错误》

# CONN_MAX_AGE的值一定要小于数据库配置的最大连接数
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxx',
        'USER': 'xxx',
        'PASSWORD': 'xxx',
        'HOST': 'xxx',
        'PORT': '3306',
        'CONN_MAX_AGE': 5*60,
    }
}

至此,可以解决绝大部分的场景错误

python后端实时通信技术python-socketio方法详解

xinyigirl阅读(1389)

一、装饰器 event和on

事件处理功能的装饰器,是用来让server端和client端识别event事件的,换句话就是如果你在一个函数体前面用了装饰器,那么server端就会一直监听websocket消息,匹配client发送的event事件,如果名称一直,那么就调用server上定义的方法进行处理。个人推荐使用@sio.event装饰器,因为这种写法比较符合大部分人的阅读代码的习惯,而且server的代码和功能看着比较清晰明了。

1、event(* args,** kwargs )

  • 功能: 事件处理功能装饰器,添加了之后就代表这是用来处理socketio事件,函数名称就是event事件名称。
  • 用法:
    @sio.event
    def my_event(data):
    print('Received data: ', data)

2、on(event,handler = None,namespace = None )

  • 功能:事件处理功能装饰器,添加了之后就代表这是用来处理socketio事件
  • 参数说明:
    • event –事件名称。它可以是任何字符串。事件名称’connect’,’message’并且’disconnect’被保留,不应使用。
    • handler –处理事件时应调用的函数。如果未提供此参数,则该方法充当处理程序函数的装饰器。
    • namespace –事件的Socket.IO名称空间。如果省略此参数,则处理程序与默认名称空间关联。

来自 https://python-socketio.readthedocs.io/en/stable/api.html#server-class

  • 用法
    # as a decorator:
    @socket_io.on('connect', namespace='/chat')
    def connect_handler(sid, environ):
    print('Connection request')
    if environ['REMOTE_ADDR'] in blacklisted:
        return False  # reject# as a method:
    def message_handler(sid, msg):
    print('Received message: ', msg)
    eio.send(sid, 'response')
    socket_io.on('message', namespace='/chat', message_handler)

    二、服务器开启Server

    socketio服务器有两种类型,一种是同步的,一种是异步的。具体使用哪一种是根据你使用的http server框架强相关的,换句话就是如果你使用的是异步的。

1、同步模式

  • 函数体:socketio.Server(client_manager = None,logger = False,binary = False,json = None,async_handlers = True,always_connect = False,** kwargs )
  • 参数介绍:
    • client_manager –将管理客户端列表的客户端管理器实例。如果省略此选项,客户端列表将存储在内存结构中,但是这样就没办法使用多个连接的服务器。
    • logger –启用设置为日志记录True或传递给它使用的logger对象。要禁用日志记录,请设置为False。默认值为 False。
    • binary – True支持二进制传输数据,False将所有数据视为文本进行传输。在Python 2里,如果它被设置为True, unicode值被视为文本,str和 bytes值将被视为二进制文件。这个参数在python3是无效的
    • json –用于编码和解码数据包的替代json模块。自定义json模块必须具有dumps与loads 标准库版本兼容的和函数。
    • async_handlers –如果设置为True,则客户端的事件处理程序将在单独的线程中执行。要为客户端同步运行处理程序,请设置为False。默认值为True。
    • always_connect –设置为时False,直到连接处理程序返回除以外的其他值时False,才建议建立新连接,此时新连接将被接受。设置为时True,将立即接受连接,然后如果连接处理程序返回False断开连接,则发出连接。设置为True如果您需要从连接处理程序发出事件,并且客户端在接受连接之前收到事件时感到困惑。在其他情况下,请使用默认值False。
    • kwargs –基础Engine.IO服务器的连接参数。
      • async_mode –要使用的异步模型。有关可用选项的说明,请参阅文档中的“部署”部分。有效的异步模式是“thread”,“evenlet”,“ gevent”和“ gevent_uwsgi”。如果未提供此参数,则首先尝试“ eventlet”,然后尝试“ gevent_uwsgi”,然后尝试“ gevent”,最后尝试“thread”。然后,安装了所有依赖项的第一个异步模式将被选择。
      • ping_timeout –客户端在断开连接之前等待服务器响应的时间(以秒为单位)。默认值为60秒。
      • ping_interval –客户端ping服务器的间隔(以秒为单位)。默认值为25秒。
      • max_http_buffer_size –使用轮询传输时消息的最大大小。默认值为100,000,000字节。
      • allow_upgrades –是否允许传输升级。默认值为True。
      • http_compression –使用轮询传输时是否压缩软件包。默认值为True。
      • compression_threshold –仅在消息的字节大小大于此值时压缩消息。默认值为1024字节。
      • cookie –包含客户端会话ID的HTTP cookie的名称。如果设置为None,则不会将cookie发送给客户端。默认值为’io’。
      • cors_allowed_origins –源或允许连接到此服务器的源列表。默认情况下,仅允许相同的来源。将此参数设置 ‘*’为允许所有起源,或[]禁用CORS处理。
      • cors_credentials –在对此服务器的请求中是否允许使用凭据(cookie,身份验证)。默认值为 True。
      • monitor_clients –如果设置为True,则后台任务将确保关闭不活动的客户端。设置为False禁用监视任务(不建议)。默认值为True。
      • engineio_logger –将Engine.IO日志记录设置为True或传递使用的记录器对象。要禁用日志记录,请设置为 False。默认值为False。

2、异步模式

  • 函数体:socketio.AsyncServer(client_manager = None,logger = False,json = None,async_handlers = True,** kwargs )
  • 功能:后台开启异步Socketio服务器,支持websocket和长轮询传输两种方式
  • 参数介绍:
    • client_manager –将管理客户端列表的客户端管理器实例。如果省略此选项,则客户端列表将以内存结构存储,因此无法使用多个连接的服务器。
    • logger –启用设置为日志记录True或传递给它使用的logger对象。要禁用日志记录,请设置为False。请注意,即使logger是,也会记录致命错误False。
    • json –用于编码和解码数据包的替代json模块。自定义json模块必须具有dumps与loads 标准库版本兼容的和函数。
    • async_handlers –如果设置为True,则事件处理程序在单独的线程中执行。要同步运行处理程序,请设置为False。默认值为True。
    • kwargs –基础Engine.IO服务器的连接参数。

三、message事件和自定义事件

server跟client进行通信都是根据event事件来进行交互的,有两种方式,一种是系统内置的message事件,一种是emit自定义事件。看函数体也可以看出send是没有event参数的,因为他发送的event名称就是message。

1、send函数

  • 函数体:send(data, to=None, room=None, skip_sid=None, namespace=None, callback=None, **kwargs)
  • 功能:发送特定的message事件。区别emit(),emit()是发送自定义消息的。参数都是相同的
  • 参数说明:
    • data –要发送到一个或多个客户端的数据。数据可以是类型的str,bytes,list或dict。如果为 list或dict,则数据将序列化为JSON。
    • to –邮件的收件人。可以将其设置为客户端的会话ID以仅寻址该客户端,或者设置为应用程序创建的任何自定义会议室,以寻址该会议室中的所有客户端。如果省略此参数,则将事件广播到所有连接的客户端。
    • room – to参数的别名。
    • skip_sid –广播到房间或所有客户端时要跳过的客户端会话ID。这可用于防止将消息发送给发件人。要跳过多个sid,请传递一个列表。
    • namespace –事件的Socket.IO名称空间。如果省略此参数,则事件将发送到默认名称空间。
    • callback –如果给定,将调用此函数以确认客户端已接收到消息。传递给函数的参数是客户端提供的参数。回调功能只能在寻址单个客户端时使用。
    • ignore_queue –仅在配置消息队列时使用。如果设置为True,则事件直接发送给客户端,而无需通过队列。这效率更高,但仅在使用单个服务器进程时有效。建议始终将此参数的默认值设置为False。

2、emit函数

  • 函数体:emit(event,data = None,to = None,room = None,skip_sid = None,namespace = None,callback = None,** kwargs )
  • 功能:可以向一个或者多个客户端发送自定义事件,属于服务器主动想客户端发送内容
  • 参数说明:
    • event –事件名称。它可以是任何字符串。事件名称’connect’,’message’并且’disconnect’被保留,不应使用。
    • data –要发送到一个或多个客户端的数据。数据可以是类型的str,bytes,list或dict。如果为 list或dict,则数据将序列化为JSON。
    • to –消息收件人。可以将其设置为客户端的会话ID以仅寻址该客户端,或者设置为应用程序创建的任何自定义会议室,以寻址该会议室中的所有客户端。如果省略此参数,则将事件广播到所有连接的客户端。
    • room – to参数的别名。
    • skip_sid –广播到房间或所有客户端时要跳过的客户端会话ID。这可用于防止将消息发送给发件人。要跳过多个sid,请传递一个列表。
    • namespace –event的Socket.IO名称空间。如果省略此参数,则事件将发送到默认名称空间。
    • callback –如果给定,将调用此函数以确认客户端已接收到消息。传递给函数的参数是客户端提供的参数。回调功能只能在寻址单个客户端时使用。
    • ignore_queue –仅在配置消息队列时使用。如果设置为True,则事件直接发送给客户端,而无需通过队列。这效率更高,但仅在使用单个服务器进程时有效。建议始终将此参数的默认值设置为False。

python后端实时通信技术python-socketio介绍

xinyigirl阅读(1458)

Python-socketio其实是socket.io的一种python实现,其实在python中socketio还有一个叫[Githug]flask-socketio,看名字就能看得出来这个sockeio是和flask框架进行结合的,这篇文章对这个不做任何介绍了,因为在web框架上我们的首选是django,但是如果你自习去看flask-socketio的文档的话,你可以看出关于socketio的通信部分的语法都是一模一样的,区别大不。

一、socketio基本说明

Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5,主要特点如下:

  • 实时分析:将数据推送到客户端,这些客户端会被表示为实时计数器,图表或日志客户。
  • 实时通信和聊天:只需几行代码便可写成一个Socket.IO的”Hello,World”聊天应用。
  • 二进制流传输:从1.0版本开始,Socket.IO支持任何形式的二进制文件传输,例如:图片,视频,音频等。
  • 文档合并:允许多个用户同时编辑一个文档,并且能够看到每个用户做出的修改。

socket.io是要求前后端必须配套使用的,如果你准备在前段使用socket.io来进行websocket通信,那么服务器端就必须使用socketio,否则websocket是建立不起来的。我们都知道在前段上是没得选择的,只能使用socket.io.js来进行实现,但是在后台的选择上我们可以采用多种方式,具体可以查看socket.io官网的说明。主要有下面的几种

而我们的选择就是python版本的实现,python-socketio。

二、Python-socketio概览

Python-socketio的文档写的相对比较详细,查看官方的文档内容,一定程度能够提前让自己有比较详尽的概念和了解,但是具体编码的时候建议还是看下github上的样例,感觉英文的官方文档虽然能看懂,但是理解上总感觉有偏差,还是直接看样例代码比较靠谱。

python-socketio因为只是一个实时通信的框架,在后台上还是要依托一个http server框架来进行运行,那么在官方的文档里面,提供了很多种的实现方式,比如tornado,uwsgi,gevent等等。也包括前面提到的flask,django这些web框架。

python-socketio的server端的服务器功能跟socket.io nodejs版本的功能没啥大的区别,都包含了连接,断开,消息发送,广播等等多种消息,但是在消息体上还是有一定的区别,这点需要注意,尤其是要将nodejs实现的socket.io替换为python-socketio的时候,尤其要注意。

nodejs上server端向前台发送消息可以直接这样写

sio.emit("eventname",arg1,arg2,arg3)

然后前端获取到的就是一个数组
["eventname",arg1,arg2,arg3]

但是在python-socketio中就不能这么写,这个可以看下源码的参数

def emit(self, event, data=None, to=None, room=None, skip_sid=None,
namespace=None, callback=None, **kwargs):

# 那么在写的时候就必须把所有要发送给client前段的字段进行打包,比如使用下面的方式

sio.emit("eventname",json.dumps([arg1,arg2,arg3])),

然后前端获取到的就是另外一个结构["eventname",[arg1,arg2,arg3]]

这样就能确保前段无感了。

其他地方几乎没有变化,直接替换即可。

前后端交互实时通信技术简述

xinyigirl阅读(890)

之前从来没有了解过socketio,或者说连polling、websocket此类全双工通信协议的使用概念都没有,但是突然要做一个使用此类技术的项目,于是赶鸭子上架,开学了扫盲和搬码,在搬码之前总得让自己有一些基础的概念,下面是从网络上了解到和收集到的一些知识。

一、综述

1、http:

http是一种面向连接(基于TCP协议)的单向的通信协议,总的来说就是客户端发送一个request请求(GET、POST、PUT……),然后服务器接到请求之后,经过后台的处理,将数据通过response发送回客户端。从这个简单的描述可以看出,服务器是一个被动接收者。更加详细的内容可以参见http协议说明,或者这篇通俗的文章——《HTTP粗解》(人家原名叫详解,说实在的详的太粗……)

但是我们在很多的实际应用中,我们是需要前后端保持一种实时的通信的,又或者说服务器也需要能够主动联系到客户端,或者我们需要实时从服务器获取最新的数据(如股票交易等),总不能让用户不停的刷新浏览器吧,比如我们的即时通信,又比如我们现在的各种直播啊,聊天室啊等等。这样就慢慢延伸出来了新的技术

2、Comet

Comet:它会延迟完成 HTTP 响应以将消息传递到客户端。基于 Comet 的推送一般采用 JavaScript 实现并使用长连接或流等连接策略。 基于 HTTP 长连接的“服务器推”技术。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。

3、polling

polling:浏览器定期发送 HTTP 请求并立即接收响应,这项技术是浏览器首次尝试传递实时信息。显然,如果消息传递的确切时间间隔已知,这是一个很好的解决方案,因为可以在服务器上先把需要发送的信息准备好之后在发送给客户端。然而,实时数据通常是不可预测的,这必然造成许多不必要的请求,因此,在低频率消息的情况下,许多连接被不必要地打开和关闭的

4、Long-Polling (长轮询)

Long-Polling (长轮询):长轮询是让服务器在接收到浏览器所送出 HTTP 请求后,服务器会等待一段时间,若在这段时间里面服务器有新的消息,它就会把最新的消息传回给浏览器,如果等待的时间到了之后也没有新的消息的话,就会送一个回应给浏览器,告知浏览器消息没有更新。虽然轮询可以减少产生原本轮询造成网络带宽浪费的情况,但是,如果在资料更新频繁的状况下,长时间轮询不传统比传统的轮询有效率,而且有时候资料量很大时,会造成连续的轮询不断产生,反而会更糟糕。

5、WebSocket

WebSocket:是一种在单个TCP连接上进行全双工通信的协议。在WebSocket API中,浏览器和服务器只需要完成一次握手(不是指建立TCP连接的那个三次握手,是指在建立TCP连接后传输一次握手数据),两者之间就直接可以创建持久性的连接,并进行双向数据传输。Websocket使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket协议使用80端口;运行在TLS之上时,默认使用443端口。

6、Socket.IO

Socket.IO :原本一个面向实时 web 应用的 JavaScript 库,现在已成为拥有众多语言支持的Web即时通讯应用的框架。Socket.IO 主要使用WebSocket协议。但是如果需要的话,Socket.io可以回退到几种其它方法,例如Adobe Flash Sockets,JSONP拉取,或是传统的AJAX拉取,并且在同时提供完全相同的接口。尽管它可以被用作WebSocket的包装库,它还是提供了许多其它功能,比如广播至多个套接字,存储与不同客户有关的数据,和异步IO操作。Socket.IO 不等价于 WebSocket,WebSocket只是Socket.IO实现即时通讯的其中一种技术依赖,而且Socket.IO还在实现WebSocket协议时做了一些调整

二、Websocket和Socket.io的优缺点对比

1、websocket技术

  • 节省资源开销:服务器到客户端的内容,头部大小只有2至10字节(和数据包长度有关),而HTTP请求每次都要携带完整的头部。
  • 更强的实时性:因为协议是全双工的,所以服务器可以随时主动给客户端下发数据。
  • 保持连接状态:Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
  • 更好的二进制支持:Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
  • 可扩展:Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
  • 更好的压缩效果:相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。
  • 没有同源限制:客户端可以与任意服务器通信。
  • 可以发送文本,也可以发送二进制数据。

2、Socket.io

  • 优点:Socket.IO 会自动选择合适双向通信协议,仅仅需要程序员对套接字的概念有所了解。有Python库的实现,可以在Python实现的Web应用中去实现IM后台服务。
  • 缺点:Socket.io并不是一个基本的、独立的、能够回退到其它实时协议的WebSocket库,它实际上是一个依赖于其它实时传输协议的自定义实时传输协议的实现。该协议的协商部分使得支持标准WebSocket的客户端不能直接连接到Socket.io服务器,并且支持Socket.io的客户端也不能与非Socket.io框架的WebSocket或Comet服务器通信。因而,Socket.io要求客户端与服务器端均须使用该框架。

参考帖子内容如下
1)即时通信WebSocket 和Socket.IO

2)【HTTP协议】—HTTP协议详解

Centos安装Python3新手教程

xinyigirl阅读(423)

序言:虽然linux系统已经内置了python,尤其是yum等工具也是要依赖python运行,但是大家都知道linux内置的是python2.7.而根据python最新的规划,python2.7将在2020年开始不在支持,也不在更新,因此现在几乎所有用python的人都转向了python3.X。那么如何安装python3呢?如何按准过python3之后又不影响linux系统中yum等工具依赖Python2.7的环境呢?

一、环境准备

其实既然你有安装python3的需求,证明你是一个有开发需求的人,那么在安装python3之前,我们要yum一些基础的包或者底层包。

  • 切换root用户:输入 sudo su – 或者 su -u root 进行root账号切换

  • 通过yum工具安装依赖的底层包:

    yum groupinstall "Development tools"
    yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-develtk-devel gdbm-devel db4-devel libpcap-devel xz-devel libfii-devel
  • 上面的执行在执行中有时候会出现找不到目录或者文件夹等错误,根据我后面使用的情况,可以忽略不计,没啥影响(可能有,还没发现)

  • 如果你的linux中没有wget,可以提前安装wget工具,以便在线下载源码进行编译安装。

    yum -y install wget

    二、开始安装

    大体步骤就是,先下载python3.X的源码,然后源码安装;修改建立python3的软连接(有点类似windows的环境变量,让centos能够在任意目录下识别python和pip命令);修改centos系统yum等工具的运行环境,否则无法运行。

  • 下载源码:有两种方式

    • 如果你系统联网的,在https://www.python.org/downloads/source/ 找到你要安装的python3.x版本,找到Gzipped格式的源码,右键复制链接即可
    • 输入wget https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tgz
    • centos会自动下载文件
    • 如果wget下载不下来,建议提前下载源码,通过winscp连接到centos主机,直接上传。
  • 解压,编译,安装

    • 提前创建好python3的安装路径文件夹,比如 mkdir /usr/local/python3
    • 解压:tat -zxvf Python-3.6.8.tgz
    • 编译:
      • 进入解压后的python源码中 cd Python-3.6.8
      • 直接将编译文件制定存放到新创建的python3文件夹里面 ./configure –prefix=/usr/local/python3./config
      • 开始编译:make
      • 安装:make install
  • 配置环境变量:分四步,先移除python2的,再创建python3的

    mv /usr/bin/python /usr/bin/python.bak
    ln -s /usr/local/bin/python3 /usr/bin/python
    mv /usr/bin/pip /usr/bin/pip.bak
    ln -s /usr/local/bin/pip3 /usr/bin/pip

    注意:第三步可能会报错,提示文件不存在之类的,这是因为centos之前就没有创建python2的环境变量,没关系

  • 验证:输入python,看到提示的版本号编程3了吧,输入pip也会看出是python3的环境.

三、修改yum配置

这个时候如果你执行yum instlall XXX 你会发现centos报错,这是因为你修改了centos自带的2.7的版本,而且修改了环境变量等配置为python3,但是yum命令执行依赖的是2.7;

前面的安装步骤其实我们只是安装,没有任何删除python2.7的操作,所以centos里面还是有python2.7的,因此我们只需要强制yum执行采用python2.7的环境即可。

  • 修改yum配置文件(vi /usr/bin/yum),把文件头部的#!/usr/bin/python改成#!/usr/bin/python2.7保存退出即可。
  • 修改/usr/libexec/urlgrabber-ext-down文件(vi /usr/libexec/urlgrabber-ext-down),把文件头部的#!/usr/bin/python改成#!/usr/bin/python2.7保存退出即可。

至此,全部搞定,大功告成,你可以愉快的使用Python3开启编程啦。

django错误:BLOB/TEXT column '*' used in key specification without a key length解决办法

xinyigirl阅读(534)

错误信息

 File "D:\pythonProject\spiderapi\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "D:\pythonProject\spiderapi\venv\lib\site-packages\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "D:\pythonProject\spiderapi\venv\lib\site-packages\MySQLdb\cursors.py", line 206, in execute
    res = self._query(query)
  File "D:\pythonProject\spiderapi\venv\lib\site-packages\MySQLdb\cursors.py", line 319, in _query
    db.query(q)
  File "D:\pythonProject\spiderapi\venv\lib\site-packages\MySQLdb\connections.py", line 259, in query
    _mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1170, "BLOB/TEXT column 'value' used in key specification without a key length")

错误原因

TextField类型在django中是不需要设置长度限制的,但是如果这个text类型被你设为了unique=True或者在unique_together中作为联合索引使用的话,那就会出现这个错误。
这个错误是mysql数据库出的,和django其实没啥关系。

详细步骤

1、修改model

有两种方式

  • 将这个字段从unique或者unqiue_together中删除掉
  • 将类型改为CharField类型并设置长度。

2、重新同步数据库

python manage.py makemigrations
python manage.py migrate

3、如果重新同步失败,那是因为上次错误时候的makemigrations文件已经生成

删除最新的一个migrations记录

4、重新同步数据库

python manage.py makemigrations
python manage.py migrate

测试付费

xinyigirl阅读(640)

测试付费阅读

[$]不知道是啥[/$]

Python-socketio介绍02(Server端)

xinyigirl阅读(1013)

一、装饰器 event和on

事件处理功能的装饰器,是用来让server端和client端识别event事件的,换句话就是如果你在一个函数体前面用了装饰器,那么server端就会一直监听websocket消息,匹配client发送的event事件,如果名称一直,那么就调用server上定义的方法进行处理。个人推荐使用@sio.event装饰器,因为这种写法比较符合大部分人的阅读代码的习惯,而且server的代码和功能看着比较清晰明了。

函数体: event(* args,** kwargs )
功能: 事件处理功能装饰器,添加了之后就代表这是用来处理socketio事件,函数名称就是event事件名称。
用法: @sio.event

def my_event(data):

print(‘Received data: ‘, data)

 

函数体: on(event,handler = None,namespace = None )
功能: 事件处理功能装饰器,添加了之后就代表这是用来处理socketio事件
参数说明:
      • event –事件名称。它可以是任何字符串。事件名称’connect’,’message’并且’disconnect’被保留,不应使用。
      • handler –处理事件时应调用的函数。如果未提供此参数,则该方法充当处理程序函数的装饰器。
      • namespace –事件的Socket.IO名称空间。如果省略此参数,则处理程序与默认名称空间关联。

来自 <https://python-socketio.readthedocs.io/en/stable/api.html#server-class>

用法: # as a decorator:
@socket_io.on(‘connect’, namespace=’/chat’)
def connect_handler(sid, environ):
print(‘Connection request’)
if environ[‘REMOTE_ADDR’] in blacklisted:
return False  # reject# as a method:
def message_handler(sid, msg):
print(‘Received message: ‘, msg)
eio.send(sid, ‘response’)
socket_io.on(‘message’, namespace=’/chat’, message_handler)

来自 <https://python-socketio.readthedocs.io/en/stable/api.html#server-class>

(更多…)