V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
guolingbing
V2EX  ›  Python

问一个比较蠢的问题,但一直没有想到好的办法 django rest framework

  •  
  •   guolingbing · 2017-03-10 15:03:45 +08:00 · 3159 次点击
    这是一个创建于 2821 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设我有两个 Serializer 在一个文件里

    class A_Serializer():
        b = B_Serializer()
    
    class B_Serializer():
        a = A_Serializer()
    

    我想把这两个 serializer 都可以嵌套的形式获取关联的属性, 但这样上方的 A 就会报 B_Serializer not define 问题,各位 dalao 有什么好办法吗

    第 1 条附言  ·  2017-03-10 15:52:39 +08:00
    class A_Serializer():
        #b = B_Serializer()
        @property
        def b():
            return B_Serializer()
    
    class B_Serializer():
        a = A_Serializer()
    

    这样好像也是不管用的

    13 条回复    2017-03-11 11:36:26 +08:00
    phithon
        1
    phithon  
       2017-03-10 15:19:42 +08:00
    同问。
    abc950309
        2
    abc950309  
       2017-03-10 15:24:05 +08:00   ❤️ 2
    用 @property
    B_Serializer()是在定义 A_Serializer 时执行的, B_Serializer 还没定义,当然会 not define 。
    改成 @property ,等待运行时获取,再缓存一下就好啦~~
    eric6356
        3
    eric6356  
       2017-03-10 15:37:19 +08:00   ❤️ 1
    是我的话会考在 __init__ 里动态地添加 self.fields
    guolingbing
        4
    guolingbing  
    OP
       2017-03-10 15:50:50 +08:00
    @abc950309 我试了,但好像并不起作用 2333
    @eric6356 self.fields 是可以修改 fields 段,但好像并不能解决引用问题,在前面定义的类怎么才能引用后面定义的类呢?
    abc950309
        5
    abc950309  
       2017-03-10 16:03:09 +08:00
    ```python
    class A_Serializer():
    #b = B_Serializer()
    @property
    def b(self):
    if not hasattr(self, '_b'):
    self._b = B_Serializer()
    return self._b


    class B_Serializer():
    a = A_Serializer()
    ```
    应该这么写哈~~没有 self 怎么搞~~手动苦笑~~
    guolingbing
        6
    guolingbing  
    OP
       2017-03-10 16:32:25 +08:00
    @abc950309 我实际上是加了 self 的,虽然没报错,但是实际上没有起作用, b 被默认设置为 PrimaryKeyRelatedField 了
    EchoUtopia
        7
    EchoUtopia  
       2017-03-10 16:33:46 +08:00   ❤️ 1
    这不就形成环了么,另外 not defined 应该是 python 会顺序执行代码,在 A_serializer 里面调用了 B_serializer ,但是这个时候 B_serializer 还没定义,所以就报错了
    guolingbing
        8
    guolingbing  
    OP
       2017-03-10 16:39:14 +08:00
    @EchoUtopia 这么一说我才明白了,果然这样就成环了,哈哈, 23333
    JerryZhang
        9
    JerryZhang  
       2017-03-10 16:45:55 +08:00   ❤️ 1
    不要这么初始化,循环引用了,如果是 C++ 的话,可以用指针。

    一个解决方案是:依赖注入:

    class A_Serializer():
    def __init__(self):
    self.b = None

    def push_ass(self, b):
    b = b

    class B_Serializer():
    def __init__(self):
    self.a = None

    def push_ass(self, a):
    self.a = a


    if __name__ == '__main__':
    a = A_Serializer()
    b = B_Serializer()
    a.push_ass(b)
    b.push_ass(a)
    guolingbing
        10
    guolingbing  
    OP
       2017-03-10 16:56:32 +08:00
    @JerryZhang 对啊,一开始我也没意识到循环引用的问题,但是写 restframework 好像不能控制的这么精细,现在我又写了一个基本类放在 A 前面就好了,虽然看起来有点不爽,还好我没有强迫证
    latyas
        11
    latyas  
       2017-03-10 17:20:52 +08:00
    def xxx():
    return B_Serializer()

    @property
    def b():
    return xxx()

    这样呢
    purebluesong
        12
    purebluesong  
       2017-03-10 20:53:02 +08:00   ❤️ 1
    DRF 用了 metaclass 来构造序列器, 楼上这些解决方法等搞定楼主的期望的时候早就迟了
    话说楼主为什么会有这么诡异的需求.......
    没必要严格遵循 REST 那套东西的,死套只会越来越复杂,搞成这样一定是哪里的设计出问题了
    guolingbing
        13
    guolingbing  
    OP
       2017-03-11 11:36:26 +08:00
    @purebluesong
    这个需求还行啊,感觉并不诡异 2333
    比如说一个 blog 关联了 comment ,我就想在 blog_detail 里嵌套返回 comment 内容
    而对一个 comment ,我也想嵌套返回所属的 blog 的基本信息
    当然这个例子不大恰当~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2642 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:44 · PVG 09:44 · LAX 17:44 · JFK 20:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.