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

2022-04-25 21:19:12 +08:00
 maloneleo88
.....


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)
    .......

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

2508 次点击
所在节点    Python
34 条回复
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
2022-04-25 22:59:59 +08:00
@westoy
@mimzy
搞不定啊,不会弄。我也感觉这样不好,太复杂了。你们写的我都看不懂,哎 太难了。。。

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

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

假设,你有数据库有 30 条数据,那么第 31 条 id 就是 31.
此时进行了一次删除,数据库就又剩 30 ,那么第 32 条的 id 又是 31 了
wnh3yang
2022-04-26 11:19:17 +08:00
bug 就是這麽來的
nonduality
2022-04-26 11:54:16 +08:00
如果没有特殊要求,最好用数据库的自增 id (整数或 uuid 都可以),只需把字段增加一属性 primary=True 。没事别自己 hack 。
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
2022-04-27 08:24:21 +08:00
感谢大家回复,其实我后来想了下也是没必要的。就是个编号问题,甚至不需要写库里,直接 html 循环出编号就可以了 😐😐😐
954
2022-04-28 09:32:30 +08:00
@westoy
这个能过 migrate 吗...
官方原文:lambda 不能用于 default 等字段选项,因为它们不能被 迁移序列化。
954
2022-04-28 09:46:05 +08:00
@mimzy
这个直接 Unresolved reference 了吧...
954
2022-04-28 09:57:42 +08:00
@wingor2015
用 count 做也不合理,最好用最后一个的 id + 1 来做吧...
除非顺手再把 delete 重写了,不然删除后会导致重复 choice_id 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/849243

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX