django models 自定义方法报错,我这哪里写的有问题? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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
maloneleo88

django models 自定义方法报错,我这哪里写的有问题?

  •  
  •   maloneleo88 Apr 25, 2022 3692 views
    This topic created in 1465 days ago, the information mentioned may be changed or developed.
    ..... class Detect(models.Model): def chioce_id(self): data = self.objects.all() id = len(data) + 1 return id detect_id = models.BigIntegerField(verbose_name='编号',default=chioce_id) ....... 

    为什么一直报我错呢? 我想弄个可自填可手改的序号, 这方法在类里不能用吗?有别的法吗?

    34 replies    2022-04-28 09:57:42 +08:00
    blueaurora
        1
    blueaurora  
       Apr 25, 2022
    虽然你没有把错误的 log 贴上来,但是能发现一个错误: data = self.objects.all() .把 self 改成 Detect ,即:

    data = Detect.objects.all()

    因为 objects 是类中的,不是实例中的
    blueaurora
        2
    blueaurora  
       Apr 25, 2022
    至于 default=choice_id , 我感觉也是不对的.. 因为 choice_id 方法 却是实例中的,但字段又是类中的..
    maloneleo88
        3
    maloneleo88  
    OP
       Apr 25, 2022
    @blueaurora 错误就是找不到定义的函数 , 谢谢!

    类这里永远也搞不明白
    blueaurora
        4
    blueaurora  
       Apr 25, 2022
    把 detect_id 的修改逻辑从字段的 default 里摘出来吧。 不要写在 model 类的定义当中了吧
    blueaurora
        5
    blueaurora  
       Apr 25, 2022
    @maloneleo88 嗯嗯,default 的这个,我只是感觉可能有问题,但如果你跑通了那就忽略质疑吧, 这就是 python..
    maloneleo88
        6
    maloneleo88  
    OP
       Apr 25, 2022
    @blueaurora 所以应该怎么做才对呢, 如你所料

    进添加页面直接报
    chioce_id() missing 1 required positional argument: 'self'
    blueaurora
        7
    blueaurora  
       Apr 25, 2022
    在 java 中,类一般都是静态写好的;但在 python 中,动态创建新类和修改类 跟玩似的
    maloneleo88
        8
    maloneleo88  
    OP
       Apr 25, 2022
    @blueaurora 真的是到处都弄不明白,我一般是弄不了了就上 js 魔改 - -!
    blueaurora
        9
    blueaurora  
       Apr 25, 2022
    @maloneleo88 啊,比如这里 default 就是 0 或 -1 ; 然后 detect_id 的变化逻辑,写在业务中,比如重写 model 的 save ,在 save 时 去修改 detect_id
    maloneleo88
        10
    maloneleo88  
    OP
       Apr 25, 2022
    @blueaurora 你的意思是在 views 里直接拿到 queryset 再往表单 val 里填吧
    gotounix
        11
    gotounix  
       Apr 25, 2022
    函数写到类外面,不用参数,self 换成 Detect
    westoy
        12
    westoy  
       Apr 25, 2022
    你这个 chioce_id 的生成有点太暴力的啊..........
    maloneleo88
        13
    maloneleo88  
    OP
       Apr 25, 2022
    @gotounix 放外面不行 NameError: name 'Detect' is not defined
    maloneleo88
        14
    maloneleo88  
    OP
       Apr 25, 2022
    @westoy 哈哈 给出个招
    maloneleo88
        15
    maloneleo88  
    OP
       Apr 25, 2022
    @gotounix 反正是扔上面找不到类, 扔下面好不到函数。 扔里面就报错
    mimzy
        16
    mimzy  
       Apr 25, 2022
    @classmethod
    def choice_id(cls):
    ....data = cls.objects.all()
    ....return len(data) + 1

    确实太暴力了。
    mimzy
        17
    mimzy  
       Apr 25, 2022
    @classmethod
    def choice_id(cls):
    ....count = cls.objects.count()
    ....return count + 1
    maloneleo88
        18
    maloneleo88  
    OP
       Apr 25, 2022
    @mimzy 大佬! 然后怎么调用? 这个没学到过
    mimzy
        19
    mimzy  
       Apr 25, 2022
    @mimzy #16 #17 这两种写法应该有幻读( Phantom Read )的问题
    westoy
        21
    westoy  
       Apr 25, 2022
    @maloneleo88

    metaclass 要在类定义里搞到类名要用黑魔法的

    比如你这个
    from werkzeug.utils import import_string

    ......

    choice_id = models.IntegerField(
    default = (lambda m=f"{__module__}.{__qualname__}": lambda:import_string(m).objects.aggregate(current=models.Count("pk")+1)['current'])()
    )

    不过不建议使用, 代码还是写的清楚一点比较好
    maloneleo88
        22
    maloneleo88  
    OP
       Apr 25, 2022 via iPhone
    @westoy
    @mimzy
    搞不定啊,不会弄。我也感觉这样不好,太复杂了。你们写的我都看不懂,哎 太难了。。。

    我莫不如挂个 js 看看上一条编号是几然后 val+1
    westoy
        23
    westoy  
       Apr 25, 2022
    @maloneleo88

    直接 default=lambda : Detect.objects.aggregate(current=models.Count("pk")+1)['current'] 啊
    xhzhang
        24
    xhzhang  
       Apr 26, 2022
    这是要实现 id 递增吗?为什么不用 sequence 之类的,要用这么暴力的方法呢
    xhzhang
        25
    xhzhang  
       Apr 26, 2022
    看你这个是要支持自填,非自填情况下要取当前总条数+1 。
    这个 id 如果是有唯一要求,自填的 id 还要先检查是否已有 ,并抛出错误。
    如果没有唯一性要求,那就没有必要加个 choice_id 这种方法,用 uuid ,rangdom 之类的生成随机序列作为编号,另外加一个字段建立 sequence 用于区分不同的数据。
    主要是不懂为何会有你现在这种需求,没有业务目标直接写代码,感觉怪怪的
    ray5173
        26
    ray5173  
       Apr 26, 2022
    写外面没问题的,不知道你用的那个版本的 django ,我用 1.10 ,代码里有一个类似的需求(默认取当前最大值+1),就是通过 chioce_id 函数放外面实现的。
    45HXlKzal6W56zUJ
        27
    45HXlKzal6W56zUJ  
       Apr 26, 2022
    楼主听我的,django 默认有个 id 就是自增的,所以如果不是特别需要,你这个 id 字段没有必要创建。
    第二, 你这个 id 的算法有严重的问题!!!!!!

    假设,你有数据库有 30 条数据,那么第 31 条 id 就是 31.
    此时进行了一次删除,数据库就又剩 30 ,那么第 32 条的 id 又是 31 了
    wnh3yang
        28
    wnh3yang  
       Apr 26, 2022
    bug 就是麽的
    nonduality
        29
    nonduality  
       Apr 26, 2022
    如果没有特殊要求,最好用数据库的自增 id (整数或 uuid 都可以),只需把字段增加一属性 primary=True 。没事别自己 hack 。
    wingor2015
        30
    wingor2015  
       Apr 26, 2022
    dicc 的意见非常重要,自己定义 id 没有这么简单,但是如果你一定要这么做呢,也能实现

    chioce_id 这个方法应该放到 class Detect 定义的外面,才能正确找到,但是放到外面就无法获取到 objects.count (不要用 all 再 len )
    要实现的这个逻辑的话,你可以放到 save 方法里
    detect_id = models.BigIntegerField(verbose_name='编号',default=None)

    def save(self, *args, **kwargs):
    if not self. detect_id:
    self. detect_id = self.__class__.objects.count() + 1
    super(Detect, self).save(*args, **kwargs)
    maloneleo88
        31
    maloneleo88  
    OP
       Apr 27, 2022 via iPhone
    感谢大家回复,其实我后来想了下也是没必要的。就是个编号问题,甚至不需要写库里,直接 html 循环出编号就可以了
    954
        32
    954  
       Apr 28, 2022
    @westoy
    这个能过 migrate 吗...
    官方原文:lambda 不能用于 default 等字段选项,因为它们不能被 迁移序列化。
    954
        33
    954  
       Apr 28, 2022
    @mimzy
    这个直接 Unresolved reference 了吧...
    954
        34
    954  
       Apr 28, 2022
    @wingor2015
    用 count 做也不合理,最好用最后一个的 id + 1 来做吧...
    除非顺手再把 delete 重写了,不然删除后会导致重复 choice_id 。
    About     Help     Advertise     Blog     API     FAQ     Solana     5376 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 67ms UTC 06:05 PVG 14:05 LAX 23:05 JFK 02:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86