Django - 将额外的参数传递给默认的可调用函数

Django - passing extra arguments into default callable function

原标题:无法使 import 正常工作

我正在尝试生成一个函数,该函数将创建一个随机字母数字并将其作为 django 中模型字段的默认值。

所以对于单个模型,我是这样做的:

# utils.py
def generate_random_unique_code_for_model():
    from .models import mymodel 
    while 1:
        code = random_code()  #my custom function to generate random alphanumeric
        try:
            mymodel.objects.get(myfield=code)
        except mymodel.DoesNotExist:
            return code

 #models.py
 class mymodel(models.Model):
     #other fields
     myfield = models.CharField(default=generate_random_unique_code_for_model)

这段代码工作正常,但现在我必须为另一个模型提供类似的功能,所以为了遵循 DRY 原则,我试图使模型、字段名动态化。所以基本上我试图在我的 generate_random_unique_code_for_model 函数中完成 from some_app.models import some_model .

def get_model(location, model_name):
    try:
        module = __import__('.'.join(location), globals(), locals(), [model_name], -1)
        model_instance = getattr(module, model_name)
    except:
        raise ImportError(_('Could not import %(model_name)s from %(location)s') % {'model_name': model_name,
                                                                                    'location': '.'.join(location)})
    return model_instance


def generate_random_unique_code_for_model(location, model_name, field_name):
    model_object = get_model(location, model_name)
    kwargs = {field_name: ''}
    while 1:
        code = random_code()
        kwargs[field_name] = code
        try:
            model_object.objects.get(**kwargs)
        except model_object.DoesNotExist:
            return code
#models.py
class mymodel_name(models.Model):
    #other fields
    myfield_name = models.CharField(default=generate_random_unique_code_for_model(['myapp_name', 'mymodel_name'], 'myfield_name'))      

调试时,当我在调试时执行 dir(module) 时,我在列表中看不到 mymodel_name。请问有什么解决方法吗?

问题是默认采用可调用函数,因此无论何时实例化模型实例,都会调用默认函数。但是由于我在第二种情况下调用了该函数,每当服务器启动并加载模型时,它都会在创建模型 class 之前尝试加载模型。所以问题归结为将带参数的可调用函数传递给默认值,这在目前是不可能的。所以我所做的是:

def make_random():
    return generate_random_unique_code_for_model(['myapp_name', 'mymodel_name'], 'myfield_name')


class mymodel_name(models.Model):
    #other fields
    myfield_name = models.CharField(default=make_random)