V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
firejoke
V2EX  ›  Django

django 内 A 接口将 request 转发到 B 接口, 获取返回, 再继续 A 接口的逻辑,都有哪些方法?

  •  
  •   firejoke · 2019-05-17 15:56:42 +08:00 · 4111 次点击
    这是一个创建于 2002 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景:
    有一个接口, 接受请求返回一个状态信息
    另一个接口, 有一小段逻辑需要跟据状态信息做相应的处理
    不想重复写查询代码, 想着直接从 A 接口获取接口
    目前我试过的只有这一个 A.py

    from django.views.generic import View
    from django.http import JsonResponse, HttpResponseRedirect
    
    
    class A(View):
    
        def get(self, request, *args, **kwargs):
            return HttpResponseRedirect('/')
    
    	def post(self, request, *args, **kwargs):
            result_dict = {'res': 'Test'}
            return JsonResponse(result_dict)
    

    B.py

    import json
    
    from django.views.generic import View
    from django.http import JsonResponse, HttpResponseRedirect
    
    from .A import A
    
    
    class B(View):
    
        def get(self, request, *args, **kwargs):
            return HttpResponseRedirect('/')
    
        def post(self, request, *args, **kwargs):
            view = A.as_view()
            res = view(request)
            res = res.getvalue()
            res = json.loads(res)['res']
            result_dict = {'res': self._logic(res)}
            return JsonResponse(result_dict)
    
        def _logic():
            if res == 1:
                ......
                return 1
            elif == 2:
                ......
                return 2
            else:
                return 0
    

    总感觉以前在哪看到过更规范的, 但忘了......

    第 1 条附言  ·  2019-05-17 17:40:08 +08:00

    再具体一点
    A.py

    import json
    
    from django.contrib.auth.mixins import LoginRequiredMixin
    from django.views.generic.base import View
    
    class A(LoginRequiredMixin, View):
    
        def get(self, request, *args, **kwargs):
            return HttpResponseRedirect('/')
    
        def post(self, request, *args, **kwargs):
            data = json.loads(request.POST.get('data', '{}'))
            result = {'res': _logic(data)}
    
        def _logic(d):
            ......
            return res
    

    B.py

    import json
    
    from django.contrib.auth.mixins import LoginRequiredMixin
    from django.views.generic.base import View
    
    class A(LoginRequiredMixin, View):
    
        def get(self, request, *args, **kwargs):
            return HttpResponseRedirect('/')
    
        def post(self, request, *args, **kwargs):
            data = request.POST.get('data')
            data = json.loads(data)
            data.update({'check': 1})
            post = QueryDict(mutable=True)
            post.update({'data': json.dumps(data)})
            request.POST = post
            res = view(request)
            res = res.getvalue()
            res = json.loads(res)
            if res['statu'] == 0:
                ......
            elif res['statu'] == 1:
                ......
            else:
                ......
    
    14 条回复    2019-05-20 11:12:54 +08:00
    so1n
        1
    so1n  
       2019-05-17 16:07:15 +08:00
    不可以函数调用吗
    40huo
        2
    40huo  
       2019-05-17 16:25:15 +08:00
    非要用接口的话可以用 Django 带的 testclient
    firejoke
        3
    firejoke  
    OP
       2019-05-17 17:19:15 +08:00
    @so1n A 接口需要从 request 中获取是否已经登陆, 然后还要获取其他信息, 所以必须把 rrequest 传过去, 并且 request 还要修改一下携带的参数
    firejoke
        4
    firejoke  
    OP
       2019-05-17 17:40:58 +08:00
    @40huo 但是接口会检测登陆信息, 可以看我更新的附言
    noobsheldon
        5
    noobsheldon  
       2019-05-17 18:10:38 +08:00 via Android
    把 A 接口写成 middleware ?
    firejoke
        6
    firejoke  
    OP
       2019-05-17 18:24:05 +08:00
    @noobsheldon 是个思路, 给定一个路由范围, 凡是访问该范围内的路由, 都先走一遍 A 的逻辑, 然后将结果加在 request 里?
    可以, 也是一个 hack 方法~
    lusi1990
        7
    lusi1990  
       2019-05-17 18:24:28 +08:00 via Android
    面向切片? before request ? 继承? 我瞎猜的
    firejoke
        8
    firejoke  
    OP
       2019-05-17 18:31:33 +08:00
    @noobsheldon 不过这样的话, 我完全可以把 A 的逻辑单独摘出来放到 util 工具模块里去,
    我现在就想知道还有没有其他的可以在 B 接口访问 A 接口的方法, 万一以后还有其他这类场景, 而 A 的逻辑又太多不好摘出来, 就需要用到这类方法了
    firejoke
        9
    firejoke  
    OP
       2019-05-17 18:34:02 +08:00
    @lusi1990 继承没必要, 并不需要 A 的所有方法, 装饰器就和上面那位要写成 middleware 的思路差不多
    noobsheldon
        10
    noobsheldon  
       2019-05-17 18:48:37 +08:00 via Android
    @firejoke 分接口的目的不就是为了分开吗…如果有公用部分直接做成 utils (如你所言)
    firejoke
        11
    firejoke  
    OP
       2019-05-17 19:24:41 +08:00
    @noobsheldon 对了, 可以用 django 的 signal 信号机制, B 接口做完一部分逻辑, 发送一个信号, A 接口接收信号, 做处理, 再发送一个信号, B 接口再接收信号
    应用场景应该是 B 接口对 C 资源做出了改变, 而 A 接口需要根据 C 资源的状态更改 D 资源, 防止其他接口访问 D 资源的时候出现幻读之类的
    比如回帖, 更新帖子内容, 通知楼主, 可以把每一个逻辑单独做出来, 防止多个接口对同一个资源多次访问
    freakxx
        12
    freakxx  
       2019-05-18 10:40:32 +08:00
    感觉有些乱来

    view 的作用是处理 request response, 没必要这么引用

    如果 A 和 B 有代码可以共用,那么就抽出来做个 Mxin 就可以,没必要交叉

    随便改了下,类似这样
    https://gist.github.com/chrisguox/4de1a0cc586055d776be818ed636cf6e
    freakxx
        13
    freakxx  
       2019-05-18 10:45:04 +08:00
    如果更复杂的情况,

    如果是基本业务代码相同,可以考虑做成 parent view 然后继承;
    如果是业务代码共用,需要做部分处理,那么在类内做成 base func,用*kwarg 来做处理,

    代码相对来说可能比较漂亮些;

    另外作为 drf 吹( django rest framework ),推荐你使用。
    firejoke
        14
    firejoke  
    OP
       2019-05-20 11:12:54 +08:00
    @freakxx
    我也喜欢 rest 风格, 有考虑后面整个用 restframework 做(反正这小项目后端完全我一个人做主~)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2871 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:13 · PVG 19:13 · LAX 03:13 · JFK 06:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.