博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LET'S DJ:web.py无缝迁移到django
阅读量:6942 次
发布时间:2019-06-27

本文共 4186 字,大约阅读时间需要 13 分钟。

  hot3.png

DO:

前提是必须要配置好django使用jinja2模版,保持与老项目模版引擎一致。

Django通用视图最基础的类是View,其他如TemplateView、RedirectView等都继承自它,具体用法参见:

由于dj默认是不支持区分get/post方法的,需要用户自己通过以下拙劣的方式来判断:

if request.method == 'GET':    doGetelif request.method == 'POST':    doPost

参考:,文中是通过url访问一个通用的视图函数来区分,然并卵,这里不适用。

查看源码 django.views.generic.base.py,发现 RedirectView 自带get、post方法,于是我这里选择继承RedirectView来实现:

from django.http import HttpResponsefrom django.views.generic import RedirectViewfrom django.shortcuts import render, redirectfrom lib import dbfrom lib.utils import Storagepool = db.database(dbn='mysql', db='test', user='root', port=3306,                   host='127.0.0.1', pw='123', charset='UTF8',                   mincached=1, maxcached=10, maxshared=10, maxconnections=10)class Base(RedirectView):    def __init__(self, **kwargs):        RedirectView.__init__(self, **kwargs)        self.config = dict(static='/static')        self.db = pool        self.session = None        x = self        class web:            def __init__(self):                self.db = db            def input(self):                tmp_dict = {}                if x.request.method == 'GET':                    parameters = x.request.GET                elif x.request.method == 'POST':                    parameters = x.request.POST                for k, v in parameters.items():                    if type(v) == list:                        if len(v) == 0:                            tmp_dict[k] = None                        elif len(v) == 1:                            tmp_dict[k] = v[0]                    else:                        tmp_dict[k] = v                return Storage(tmp_dict)            def seeother(self, url):                return redirect(url)        self.web = web()    def redirect(self, url):        return redirect(url)    def render(self, template_name, **kwargs):        d = dict(**kwargs)        d['csrf_token'] = ''        d['session'] = self.request.session        return render(self.request, template_name, d)    def get(self, request, *args, **kwargs):        result = self.GET(*args, **kwargs)        if isinstance(result, HttpResponse):            return result        return HttpResponse(result, 'application/json')    def GET(self):        return    def post(self, request, *args, **kwargs):        result = self.POST(*args, **kwargs)        if isinstance(result, HttpResponse):            return result        return HttpResponse(result, 'application/json')    def POST(self):        return

其次要解决db问题,dj默认使用自身的ORM操作DB,不近臃肿难用,而且不利于后期维护,主要是定位问题和SQL优化等。

查看web.py的db类时无意中发现一段代码,顿时心头一喜:

try:    # db module can work independent of web.py    from webapi import debug, configexcept:    import sys    debug = sys.stderr    config = storage()

原来db.py可以独立使用,不依赖webpy的接口。不禁感叹到,这才是好的设计!

上面的base类已经集成了db.py和 dbutils模块,可以直接在view中使用db连接池。

END:

通过一个简单的包装类即可将dj模拟成web.py,view类只需继承该基类然后编写GET或者POST方法即可;

同时session、request parameter、render方法都已经包装好,完全可以避免在视图中接触到dj的API,

直接返回结果无需生成HttpResponse!示例view代码如下:

from common.base import Baseimport sysclass MainView(Base):    def GET(self, id):        id = int(id)        return self.db.query('SELECT $id', {'id' : id})    def POST(self):        form = self.web.input()        a = form.get('a')        b = form.get('b')        return self.render('test.html', a=a, b=b)

以后如果闲的DT想切换到Tornado也完全不需要改view类的代码了~

TIPS:

  • 由于dj默认支持基于方法的视图,如果要使用基于类的视图同样可以,只需将url_pattern里原本的方法名改为类名并调用as_view()方法,如:

url_patterns = [ django.conf.urls.url(r'^$', Base.as_view()), ]

参考:

  • 由于dj的默认登录验证装饰器login_required不支持被包装的方法,因此不能直接在上述Base类中的GET/POST方法上使用,

同时必须在url_pattern里将视图包装使用:django.contrib.auth.decorators.login_required(Base.as_view())

参考:、

这虽然是一个8年前的bug。。。但我使用时发现还是有点问题,最好的办法是重写鉴权装饰器。

  • 如果使用了login_required装饰器,那么还要使用 django.contrib.auth 类下的 authenticate 和 login 方法判断用户是否可以登录。

如:auth.login(self.request, user)。参考:

  • dj获取请求类型没有直接的方法,必须使用蹩脚的判断才可以获得:return 'https' if request.is_secure() else 'http'
  • 如果要获得完整请求url可使用:request.build_absolute_uri() 或 request.build_absolute_uri(request.get_full_path())
  • 由于jinja2不支持 {% csrf_token %} 标签,因此post提交时dj会报错:CSRF verification failed. Request aborted

只需在表单中加上以下元素即可:(参考:)

PS. 

对dj不熟悉,文中难免疏漏,或者有更好的方案,还望指点。

anyway,麻麻再也不用担心我用什么web框架了,除了flask……

转载于:https://my.oschina.net/cwalet/blog/668267

你可能感兴趣的文章
nginx权限
查看>>
windows 2003自动登录的具体步骤
查看>>
如何利用脚本自动化挂载数据盘?
查看>>
mysql数据库-备份
查看>>
root用户被误设置成nologin
查看>>
VIII virtualization&kvm
查看>>
OpenStack Rabbit 集群实现
查看>>
让服务开机自动启动
查看>>
4.部署Sentinel
查看>>
Top 10 Methods for Java Arrays
查看>>
iptables基本知识
查看>>
[Fibre Channle 实战之三]FC 和iSCSI的使用差异
查看>>
MySQL索引 使用笔记
查看>>
LTS/SSL理解
查看>>
PHP file_get_contents 设置超时时间
查看>>
状态与策略——审批操作的两种方案
查看>>
xargs用法详解
查看>>
Linux运维工程师面试题第一套
查看>>
Linux Stateless无状态NAT-使用TC来配置
查看>>
微软的上海之约——写在微软中国上海科技园区开幕之际
查看>>