在Django模型中存储函数调用

时间:2018-07-13 12:48:07

标签: python django dictionary django-models

当前,我将一系列对象存储为字典的字典,并且在其中存储对在字典外部定义的函数的调用。这些功能是特定于对象的,不能一概而论。在字典中,我可以直接引用该函数,例如:'some_property': function_name,稍后在dictionary['some_property'](arg_1, arg_2)上调用该函数时,该函数将被调用。我正在将字典词典迁移到Django模型,但是我看不到如何从模型中复制此功能。

我目前拥有的东西:

dictionaries.py

def year_camel_month(filename, **kwargs):
    month = kwargs['month'].title()
    return filename.format(str(kwargs['year']), month)


def year_month(filename, **kwargs):
    month = kwargs['month']
    return filename.format(str(kwargs['year']), month.lower())


data_source_families = {
    'dataset_1': {
        'source_url': 'https://example.org/url/subfolder',
        'slug': 'slug_that_changes_predictably_over_time{}-{}',
        'slug_treatment': year_camel_month
    },
    'dataset_2': {
        'source_url': 'https://example2.org/url/subfolder',
        'slug': 'slug_that_changes_predictably_over_time{}-{}',
        'slug_treatment': year_month
        },
}

随后在与用户定义的时间范围结合使用时会被调用:

get_data.py

from .dictionaries import data_source_families

slug = data_source_families[selected_dataset]['slug']
processed_slug = data_source_families[selected_dataset]['slug_treatment'](slug, some_kwargs)
url = data_source_families[selected_dataset]['source_url'] + processed_slug

这很好。我正在寻求通过创建可复制此内容的Django模型来开发功能来提高一致性(并使这些数据可用于其他程序),例如:

models.py

def year_camel_month(filename, **kwargs):
    month = kwargs['month'].title()
    return filename.format(str(kwargs['year']), month)


def year_month(filename, **kwargs):
    month = kwargs['month']
    return filename.format(str(kwargs['year']), month.lower())


class DataSourceFamilies(models.Model):
    name = models.CharField(max_length=200, unique=True)
    source_url = models.CharField(max_length=300, blank=False)
    slug = models.CharField(max_length=200, blank=False)
--> slug_treatment = models._____(choices=list_of_functions)    <--

    def __str___(self):
        return self.name.name

是否存在类似的东西?我将如何去做?

3 个答案:

答案 0 :(得分:1)

您可以做的一件事是使用CharField,然后eval。但是,使用eval通常会带来巨大的安全风险。输入它的所有python代码都将被执行,并且您不希望在Web应用程序中有任何类似的代码。

另一个选择是拥有一个查找系统。您可以说,有一个CharField,其选择对应于这样的字典:

models.py
...
slug_treatment = models.CharField(max_length=100, choices=function_choices)
...

然后:

get_data.py

function_lookup = {
    "year_month": year_month,
    "year_camel_month": year_camel_month
}

processed_slug = function_lookup[data_source.slug_treatment](slug, some_kwargs)

答案 1 :(得分:1)

实际上,您不能在SQL数据库中存储函数(我指的是Python函数)。但是您可以存储任何文本值,并且模型中可以有一个“ key:func”的字典,即:

class DataSourceFamilies(models.Model):
    name = models.CharField(max_length=200, unique=True)
    source_url = models.CharField(max_length=300, blank=False)
    slug = models.CharField(max_length=200, blank=False)

    SLUG_TREATEMENTS = [
        # key, label, function
        ('year_camel_month', "Year, Camel month", year_camel_month),
        ('year_month': "Year month", year_month),
    ]  
    SLUG_TREATEMENTS_ACTIONS = {
        k: func 
        for k, label, func in SLUG_TREATEMENTS
    }

    SLUG_TREATEMENTS_CHOICES = [
        (k, label)
        for k, label, func in SLUG_TREATEMENTS
    ]

    slug_treatment = models.CharField(
        max_length=50 # let's have a little headroom, 
        choices=SLUG_TREATMENT_CHOICES
        )

    def get_slug_treatment_func(self):
        return self.SLUG_TREATEMENTS_ACTIONS[self.slug_treatment]

答案 2 :(得分:0)

对我来说有点困惑,但是根据我的理解,也许您可​​以在类中声明所有函数,并使用slug_treament作为参数,在需要时可以调用该函数。

让我们画一点

YEAR_CAMEL_MONTH=1 
YEAR_MONTH=2
SLUG_TREATEMENTS_CHOICES = [
        (YEAR_CAMEL_MONTH: 'year_camel_month'),
        (YEAR_MONTH: 'year_month'),
    ]

class DataSourceFamilies(models.Model):
    ...
    slug = models.CharField(max_length=200, blank=False)
    slug_treatment = models.IntegerField(choices=SLUG_TREATMENT_CHOICES)

    def year_camel_month(self):
        ... # Your logic
        return formated_slug

    def year_month(self):
        ... # Your logic
        return formated_slug

    def save(self *args **kwargs):
        if self.slug_treatment == YEAR_CAMEL_MONTH:
            self.slug = self.year_camel_month()
        elif self.slug_treatment == YEAR_MONTH:
            self.slug = self.year_month()
        super(DataSourceFamilies, self).save(*args, **kwargs)

或者您可以将其用作属性方法,而不是持久数据(因此,每次调用查询集时都会评估该段,因此它是动态的,而不是持久的”。 Obs 。:属性方法的工作方式类似于数据库中的列,但不能持久保存,就像数据库中的CAST

class DataSourceFamilies(models.Model):
    ...        
    slug_treatment = models.IntegerField(choices=SLUG_TREATMENT_CHOICES)

    @property
    def slug(self):
        if self.slug_treatment == YEAR_CAMEL_MONTH:
            return slug = self.year_camel_month()
        elif self.slug_treatment == YEAR_MONTH:
            return slug = self.year_month()

https://docs.djangoproject.com/en/2.0/topics/db/models/

不好。:如果您尝试从文本中获取代码并在python中对其进行评估,我想它是可能的,但是是非常不安全的,因此我不建议这样做 < / p>