V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
subpo
V2EX  ›  问与答

用 Django 写 web 写的无比痛苦,是我的问题吗?

  •  
  •   subpo · 2020-09-21 22:38:07 +08:00 · 4422 次点击
    这是一个创建于 1561 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近从 Ruby on Rails 切换到 Python on Django 。才上手写了几天,可能对 Django 理解不深刻,但是这几天真的把我恶心的想吐,这是我的问题吗?还是继续写下去就能发现这个将近 20 年的框架的优秀点?

    Python 虽然对我来说还有一点点小别扭的地方(比如明明是一切皆对象,却使用 len(obj)而不是 obj.len()),总体来说写起来还是比较爽,语法比较简单,调试工具链完善,网上能找到的资料也多。

    但是 Django 简直让我痛苦无比。

    按照官方文档,router 层无法定义请求类型,要在 ViewController 里面写 if request.method == "POST" 。
    畸形的模板系统,无法在模板层写脚本,这点我可以理解是架构的设计考虑到不想在模板层引入逻辑,但放着 python 这么有表现力的语言不用,硬是发明了一个新的模板语法,实在是理解不能。

    细节的问题更加数不胜数
    比如写一些复杂的 View,需要把同一个资源的 POST 和 GET 方法拆开写
    post /api/resources create_resource_view
    get /api/resources list_resource_view
    居然发现 Django 的 router 不支持把这种约定俗成的 RESTful api 导向不同的文件

    模板层也各种难受,API 接受到 string 格式的 date 参数,需要转成 date 格式存入数据库,这么一个任何一个 APP 都会遇到无数次的逻辑,都需要 hard coding 或三行以上的代码来处理

    API 参数验证也很糟糕,ORM 也很糟糕,一吐槽都停不下来,哪里哪里都很糟糕
    30 条回复    2020-09-22 12:53:39 +08:00
    wander639
        1
    wander639  
       2020-09-21 22:43:26 +08:00
    view 的话可以考虑下 cbv
    模板的话不知道能不能自己换成 mako
    个人觉得 django 的 orm 还是挺好用的
    Rxianbei
        2
    Rxianbei  
       2020-09-21 22:46:35 +08:00 via Android
    啊,对呀,要在 view 层定义请求方式实在是把我看得一愣一愣,这也太不优雅了。
    cyssxt
        3
    cyssxt  
       2020-09-21 22:56:33 +08:00 via iPhone
    熟能生巧
    youngce
        4
    youngce  
       2020-09-21 23:00:06 +08:00
    1. obj.__len__()是 len(obj)面向对象的写法,不主动定义为 obj.len ()是考虑到很多人也需要对这种东西自定义
    2.django 是你的理解还不够的,你列举的那些问题,django 都有完善的高级的处理办法,但是你如果只看了了一个入门教程,可能是还没接触到这些。django 属于那种需要一段时间上手的框架,不要指望一上手就掌握所有 django 特性,如果没有耐心,请使用 flask 。
    youngce
        5
    youngce  
       2020-09-21 23:02:06 +08:00
    CVB 是不要整这些 view 层定义的,路由也是完全的 rest 风格,正经写 api,也都用 drf 的,不要被一些水货教程误导了
    subpo
        6
    subpo  
    OP
       2020-09-21 23:09:32 +08:00
    @youngce #5 rest framework 有在用,我也想吐槽来着,serializer 就我个人的感觉,一般是格式化输出的东西,但是 rest framework 把 serializer 同时作用于参数输入,验证,存储和格式化输出,一些常用的功能(自定义输入验证,输出附上一些自定义字段)也没能简单的提供,都需要进行一些有些奇怪的操作。

    不过有你这么说我就放心多了...较长时间里不得不接触 Django 的话,宁愿是我自己菜
    Philippa
        7
    Philippa  
       2020-09-21 23:17:06 +08:00
    Django 起手挺复杂的,而且设计得很繁杂,很多魔法,我一开始也很难适应。我后来找到一个入门 tutorial 去写个小 demo 才慢慢入门。

    一般使用 rest_framework + Django + 一点最佳实践。用 ModelView 和 Model Serializer 那种高度抽象得语法来写,开发速度非常非常快的,而且它生态很好,除了基础功能,连 aws 等平台绑定的 libaries 也一大堆,如果你想最大化自己的开发速度,Django 一定是 Python 最好的选择,即使和其他语言的 Web 比较如 PHP 和 Ruby 也毫不逊色。

    我用 Django 写 web 大部分时间其实都是遵照 TDD 写 unittest 的,因为一般常见的 API 开发,写 view/model/serializer 等都没多少行代码,大部分代码都是 unittest 。但这种高度抽象的写法很容易出错,多一行,少一个方法可能相差非常大,不写 unittest 来 debug 是非常困难的。

    建议多花一周实践继续研究一下,我当时刚开始也觉得很痛苦= =,怎么设计那么脏,为什么要用字符串而不是类,为什么要去 override 那么多方法来实现 api 等等,中途还一度放弃去写 flask/echo,但最终尝试下来发现这值得,开发效率非常非常高,现在我个人开发都是 Django + React 。个人的 Nodejs 的 Nestjs 还是 Expressjs 的开发效率和 Django 还是差一个等级。
    subpo
        8
    subpo  
    OP
       2020-09-21 23:19:53 +08:00
    @subpo #6 我表达的不是很清楚。重新说一下

    比方说一个 api 的 create 部分的常见操作:
    1. 验证传输进来的数据的合法性,包括数据格式转换,验证等
    2. 进行一些业务逻辑后存入数据库
    3. 返回存入的字段和一些自定义字段

    这个常见的操作用 drf 怎么都走不顺。操作 1 的 serializer,操作 2 的 model,操作 3 的返回 serializer 几乎是同一样东西,但是又有一些细节不同,实现起来很别扭,不顺。

    并且个人认为 djr 的 Restful 设计的不太好,诚然做一个标准的 CURD 操作用 Viewset 非常方便用不了几行代码,但是真正放到业务逻辑里,又有多少标准又无扩展逻辑的 CURD 呢?这时,djr 需要用不同于 Viewset 的另外一套逻辑来处理这部分业务逻辑,显得非常脆弱。
    iConnect
        9
    iConnect  
       2020-09-21 23:27:59 +08:00 via Android
    如果熟悉工厂模式,换 flask 吧,django 的路由设计不如 flask 来的简洁。
    dcalsky
        10
    dcalsky  
       2020-09-22 00:11:38 +08:00 via Android
    @subpo DRF 就是开发小功能快,你要做细的话,那就得好好看看各个 serializer 以及 serializer relation 。很多逻辑要在 serialization 的 create validate save 里面做。
    comwrg
        11
    comwrg  
       2020-09-22 00:19:23 +08:00 via iPhone
    同样的感觉…
    comwrg
        12
    comwrg  
       2020-09-22 00:22:09 +08:00 via iPhone
    要不是 python 轮子多,对于个人开发者来说我还是选择 rails,而不是 python 的 web 框架
    oahebky
        13
    oahebky  
       2020-09-22 01:00:58 +08:00 via Android
    是你的问题。
    zachlhb
        14
    zachlhb  
       2020-09-22 01:14:56 +08:00 via Android
    cbv 是可以定义请求类型,class 里方法名定义成 method 就行了
    zachlhb
        15
    zachlhb  
       2020-09-22 01:18:02 +08:00 via Android
    如果写接口可以用 drf 的 viewset,然后在路由的 as_view 里面定义请求的 method 和对应的方法
    MintZX
        16
    MintZX  
       2020-09-22 01:38:47 +08:00
    ruby on rails 开发给你点个赞。。。

    确实不喜欢 django 的写法,但是新公司的技术栈就是 django 和 flask,只能被迫用了
    ericls
        17
    ericls  
       2020-09-22 02:19:07 +08:00 via iPhone
    不就是个 wsgi
    steptodream
        18
    steptodream  
       2020-09-22 07:36:15 +08:00
    我是二流搞 IT 的 被迫开发内部 web 适应尝试了一圈 发现对于我来说 django 最容理解
    wellsc
        19
    wellsc  
       2020-09-22 08:18:49 +08:00 via iPhone
    用 go 试试(手动狗头
    0312birdzhang
        20
    0312birdzhang  
       2020-09-22 08:32:05 +08:00 via iPhone
    +10086 啊,写的太痛苦了,于是我用 java 了(滑稽
    BenX
        21
    BenX  
       2020-09-22 08:38:00 +08:00 via Android
    一切原因在于你从 ror 转出来的,被 ror 伺候过,其它都不香了。
    wangkun025
        22
    wangkun025  
       2020-09-22 08:44:18 +08:00
    被 rails 惯坏了。
    最近看 spring boot,连 router 都没有。直接在 controller 里写 mapping,岂不是更加郁闷。
    Jammar
        23
    Jammar  
       2020-09-22 08:49:46 +08:00
    用 drf
    router 直接指向函数或者类(实现 as_view()方法的)
    view 层定义 method,有很多种放我,我常用在类下面 def get
    string 转 date,我没记错的话可以直接序列化,或者使用一些模块一行代码的事情,比如 datetime
    api 参数验证直接使用 serializer.is_valid()没有报错.data 获取数据
    orm 是面向对象的形式 user=User(),user.name=xxx,user.sava()
    对于一个常见的 create 操作,先写 modelserializer,再视图层验证取数据,可以看一下 drf 的 CreateAPIView
    Akkuman
        24
    Akkuman  
       2020-09-22 09:09:20 +08:00 via Android
    把 drf 的文档看完,然后边做边看源码,其实你会发现各个地方都有钩子,可控性挺强的
    37Y37
        25
    37Y37  
       2020-09-22 09:26:12 +08:00
    我不管,反正我用起来贼香,哈哈
    nonduality
        26
    nonduality  
       2020-09-22 09:33:31 +08:00
    说起来,你的抱怨来自两点:1 、缺少开放思维,带着 ROR 的固有习惯,认为 ROR 的做法才是唯一正确; 2 、对 Django 学艺不精,Django 作为广泛使用的框架,如果大家都是像你那样在忍受各种缺陷,是不可能走到现在的。

    我从来不喜欢基于函数来处理请求,喜欢用 class-based view,宁可直接继承 GenericView 来写,同一个类下定义一个 get 和一个 post 方法,然后 as_view()绑定到同一个 url,根本不会有你说的问题。

    至于模板,属于见仁见智,如果允许模板写很多代码,那就违背了逻辑和表现分离的原则,鼓励用户将更多的逻辑扔到模板里。

    API 的问题,用 DRF 。

    Django ORM 我认为很好很优雅,尽管我也可以接受 SqlAlchemy 的形式( Flask 用的是修改过的,要不更难用),但像 Pony 之类搞的黑魔法,lambda 满天飞,才叫糟糕。
    libracloud
        27
    libracloud  
       2020-09-22 10:06:40 +08:00   ❤️ 1
    用 rails 后,用啥都不爽
    linvaux
        28
    linvaux  
       2020-09-22 10:09:29 +08:00 via iPhone
    用 fastapi
    Mark24
        29
    Mark24  
       2020-09-22 10:11:19 +08:00   ❤️ 1
    体验过 rails,我选 Ruby On Rails

    Python 确实优秀

    但是 Ruby 似乎更胜一筹~
    xulolololololo
        30
    xulolololololo  
       2020-09-22 12:53:39 +08:00 via Android
    我以前也是用 django 的,但是我们都是自己定制化自己公司的业务 view,所以不涉及 django 太多奇奇怪怪的东西。然后新公司换成 sanic,也是定制了一下就写了,这 web 开发就是这么回事,框架随便换。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1096 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:23 · PVG 03:23 · LAX 11:23 · JFK 14:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.