我想编写一个通用函数来配对两个数据库字段

时间:2012-05-17 00:18:29

标签: python django metaprogramming

假设我有两个小组"red""black"。让我们说我有一个Story课程,它以两种截然不同的方式呈现类似的信息,具体取决于您的团队:

class Story(models.Model):
    red_title = models.CharField()
    black_title = models.CharField()

    red_prologue = models.TextField()
    black_prologue = models.TextField()

    # ... and so on ...

    def get_field(self, genericName, team):
        """Return the field with suffix genericName belonging to the given team.

        >>>self.get_field("prologue", "red") is self.red_prologue
        True
        >>>self.get_field("title", "black") is self.black_title
        True

        """
        assert(team in ["red", "black"])
        specificName = "{}_{}".format(team, genericName)
        return self.__dict__[specificName]

我对getter函数感到满意,但我觉得我应该能够重构首先创建字段的代码。我想要一个看起来像这样的函数:

def make_fields(self, genericName, fieldType, **kwargs):
    """Create two fields with suffix genericName.

    One will be 'red_{genericName}' and one will be 'black_{genericName}'.

    """
    for team in ["red", "black"]:
        specificName = "{}_{}".format(team, genericName)
        self.__dict__[specificName] = fieldType(**kwargs)

但是self__dict__在首次定义类时没有意义,我认为Django要求数据库字段是类变量而不是实例变量。

那么......有没有办法在Django中创建这个make_fields函数,还是我运气不好?

2 个答案:

答案 0 :(得分:1)

没有。不应将Django模型视为可以动态构造的东西;它是数据库表的Python表示。例如,在您运行specificName之后更改syncdb格式的语义是什么?没有确定的,明显的答案 - 所以Django不会试图回答它。你的列是在类级别定义的,就是那个。

(在某种程度上,您可以随时深入了解内部ORM数据结构并设置这些字段 - 但您所做的只是让自己处于一个模糊不清和定义不明确的问题的世界。做吧。)

答案 1 :(得分:1)

不确定为什么你这样做。一个更理智的模型是:

TEAMS = (
    ("r","red"),
    ("b","black"),
)

class Story(models.Model):
    team = models.CharField(max_length=1, choices=TEAMS)
    title = models.CharField()
    prologue = models.TextField()

您当前的模型正在创建大量重复列(红色和黑色),这些列应该由列本身定义。使用上面的模型,您的查询就像Story.objects.filter(team="r")

您根本不需要get_field功能。