参考字段';Django模型中的默认函数&x27;s法

参考字段';Django模型中的默认函数&x27;s法,django,django-models,Django,Django Models,有一个模型的字段应自动填充固定长度的随机标识符: from django.db import models from django.utils.crypto import get_random_string def get_random_string_fixed(): return get_random_string(length=20) class Post(models.Model): identifier = models.CharField(unique=True,

有一个模型的字段应自动填充固定长度的随机标识符:

from django.db import models
from django.utils.crypto import get_random_string

def get_random_string_fixed():
    return get_random_string(length=20)

class Post(models.Model):
    identifier = models.CharField(unique=True, default=get_random_string_fixed)
为了不确定generate值是否确实唯一,我希望在save方法中重新生成它,如果该值已经存在:

def save(self, *args, **kwargs):
    if not self.pk:
        while Post.objects.filter(identifier=self.identifier).exists():
            self.identifier = get_random_string_fixed()
    super().save(*args, **kwargs)
此实现的问题是,
get\u random\u string\u fixed
是在
save()
方法中硬编码的。如果在某个时候我决定为这个字段选择一个不同的默认函数,我将不得不在几个地方更改它,这是一个糟糕的做法

是否有一种方法可以引用分配给模型方法中字段的
默认属性的函数,而无需硬编码函数名称?

当然,您可以使用:

Post._meta.get_field("identifier").default
也就是说,我认为使用
默认值没有多大意义。无论如何,您在
save()
中重写了它,这有点误导,因为它实际上不是默认值

还要注意,您的算法仍然存在失败案例。使用默认事务隔离级别,它不会阻止两个事务同时写入相同的值。当然,这是极不可能的。

当然,您可以使用:

Post._meta.get_field("identifier").default
也就是说,我认为使用
默认值没有多大意义。无论如何,您在
save()
中重写了它,这有点误导,因为它实际上不是默认值



还要注意,您的算法仍然存在失败案例。使用默认事务隔离级别,它不会阻止两个事务同时写入相同的值。当然,这是极不可能的。

创建一个名为
identifier\u default
的函数并使用它。然后,您可以将实际功能委托给您喜欢的任何函数。谢谢,这确实是一个选项,但我希望有一种方法可以通过
class.field.default
之类的方式获得它。为什么
没有放在
get\u random\u string\u fixed()的函数中
?@SancaKembang,因为这不是
get\u random\u string\u fixed()函数的工作。这个函数可以在任何其他字段/模型中使用。我认为应该可以这样做:创建一个名为
identifier\u default
的函数并使用它。然后,您可以将实际功能委托给您喜欢的任何函数。谢谢,这确实是一个选项,但我希望有一种方法可以通过
class.field.default
之类的方式获得它。为什么
没有放在
get\u random\u string\u fixed()的函数中
?@SancaKembang,因为这不是
get\u random\u string\u fixed()函数的工作。此功能可用于任何其他领域/模型。我认为这应该是可能的,可能是这样的:非常感谢您的建议。你能详细介绍一下同时发生的独立交易吗?如何防范这些问题?默认情况下,事务只会在打开时看到数据库的状态。因此,如果在您打开交易后另一个交易保存了值
X
,您将不会在搜索中看到
X
。但是,当您尝试提交事务时,由于唯一性约束,它将失败。处理这些问题并不简单,但您可以通过乐观并发性寻找可能的解决方案。但我的建议是——不要担心检测这些冲突。使用UUID(基本上就是您正在做的事情)的全部意义在于,发生冲突的可能性很小,因此您可以忽略它。既然这样,为什么不直接使用内置的呢?因为这个
标识符将呈现给用户,应该很短,大约8-10个字符长。理想情况下,它应该类似于Git提交ID的简短版本。但是
UUIDField
对于这个目的来说太长了。Git ID是40个字符的ID,不会检查其唯一性,因为发生冲突的可能性很低。简短版本只是表示和使用这些ID的一种更简单的方法。你也可以这样做。或者,只需使用一个常规的自动递增整数(没有比
1
短的整数)。或者,如果愿意,将该唯一整数散列为8-10个字符的字符串。我们已经远离了你最初的问题,但我的观点是,这里可能有更好的方法来实现你的目标。非常感谢你的建议。你能详细介绍一下同时发生的独立交易吗?如何防范这些问题?默认情况下,事务只会在打开时看到数据库的状态。因此,如果在您打开交易后另一个交易保存了值
X
,您将不会在搜索中看到
X
。但是,当您尝试提交事务时,由于唯一性约束,它将失败。处理这些问题并不简单,但您可以通过乐观并发性寻找可能的解决方案。但我的建议是——不要担心检测这些冲突。使用UUID(基本上就是您正在做的事情)的全部意义在于,发生冲突的可能性很小,因此您可以忽略它。既然这样,为什么不直接使用内置的呢?因为这个
标识符将呈现给用户,应该很短,大约8-10个字符长。理想情况下,它应该类似于Git提交ID的简短版本。但是
UUIDField
对于这个目的来说太长了。Git ID是40个字符的ID,不会检查其唯一性,因为发生冲突的可能性很低。简短版本只是表示和使用这些ID的一种更简单的方法。你也可以这样做。或者,只需使用一个常规的自动递增整数(没有比
1
短的整数)。或者,如果愿意,将该唯一整数散列为8-10个字符的字符串。我们已经离你原来的问题很远了,但我的观点是