django models 自定义方法报错,我这哪里写的有问题? - V2EX
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
maloneleo88
V2EX    Python

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

  •  
  •   maloneleo88 2022-04-25 21:19:12 +08:00 3442 次点击
    这是一个创建于 1338 天前的主题,其中的信息可能已经有所发展或是发生改变。
    ..... 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 条回复    2022-04-28 09:57:42 +08:00
    blueaurora
        1
    blueaurora  
       2022-04-25 21:43:31 +08:00
    虽然你没有把错误的 log 贴上来,但是能发现一个错误: data = self.objects.all() .把 self 改成 Detect ,即:

    data = Detect.objects.all()

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

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

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

    确实太暴力了。
    mimzy
        17
    mimzy  
       2022-04-25 22:23:18 +08:00
    @classmethod
    def choice_id(cls):
    ....count = cls.objects.count()
    ....return count + 1
    maloneleo88
        18
    maloneleo88  
    OP
       2022-04-25 22:30:45 +08:00
    @mimzy 大佬! 然后怎么调用? 这个没学到过
    mimzy
        19
    mimzy  
       2022-04-25 22:31:26 +08:00
    @mimzy #16 #17 这两种写法应该有幻读( Phantom Read )的问题
    westoy
        21
    westoy  
       2022-04-25 22:49:10 +08:00
    @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
       2022-04-25 22:59:59 +08:00 via iPhone
    @westoy
    @mimzy
    搞不定啊,不会弄。我也感觉这样不好,太复杂了。你们写的我都看不懂,哎 太难了。。。

    我莫不如挂个 js 看看上一条编号是几然后 val+1
    westoy
        23
    westoy  
       2022-04-25 23:02:26 +08:00
    @maloneleo88

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

    假设,你有数据库有 30 条数据,那么第 31 条 id 就是 31.
    此时进行了一次删除,数据库就又剩 30 ,那么第 32 条的 id 又是 31 了
    wnh3yang
        28
    wnh3yang  
       2022-04-26 11:19:17 +08:00
    bug 就是麽的
    nonduality
        29
    nonduality  
       2022-04-26 11:54:16 +08:00
    如果没有特殊要求,最好用数据库的自增 id (整数或 uuid 都可以),只需把字段增加一属性 primary=True 。没事别自己 hack 。
    wingor2015
        30
    wingor2015  
       2022-04-26 17:54:35 +08:00
    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
       2022-04-27 08:24:21 +08:00 via iPhone
    感谢大家回复,其实我后来想了下也是没必要的。就是个编号问题,甚至不需要写库里,直接 html 循环出编号就可以了
    954
        32
    954  
       2022-04-28 09:32:30 +08:00
    @westoy
    这个能过 migrate 吗...
    官方原文:lambda 不能用于 default 等字段选项,因它们不能被 迁移序列化。
    954
        33
    954  
       2022-04-28 09:46:05 +08:00
    @mimzy
    这个直接 Unresolved reference 了吧...
    954
        34
    954  
       2022-04-28 09:57:42 +08:00
    @wingor2015
    用 count 做也不合理,最好用最后一个的 id + 1 来做吧...
    除非顺手再把 delete 重写了,不然删除后会导致重复 choice_id 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2962 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 12:43 PVG 20:43 LAX 04:43 JFK 07:43
    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