Python:类中的复合函数

时间:2016-10-27 06:43:31

标签: python django function class

我试图在Django中复制类似于模型查询的内容。

# database.py

class ModelFactory(object):
    def __init__(self, table):
        self.table = table

    def fields(self, *args):
        str_columns = ''
        for count, arg in enumerate(args):
            if count == 0:
                str_columns += arg
            else:
                str_columns += ', %s' % arg
        self.str_columns = str_columns

    def wheres(self, **kwargs):
        str_wheres = ''
        for count, (key, value) in enumerate(kwargs.items()):
            if count == 0:
                str_wheres += 'WHERE %s = %s' % (key, value)
            else:
                str_wheres += ' AND %s = %s' % (key, value)
        self.str_wheres = str_wheres

我的想法是按如下方式使用它:

from database import ModelFactory

myInstance = ModelFactory('myTable')
myQuery = myInstance.fields('column1', 'column2').wheres(column1 = 5)

我不确定我是否需要在ModelFactory类中使用新类或函数来获取'字段'并且''s'编译一个SQL字符串来查询?如下所示:

cur.execute('SELECT column1, column2 from myTable WHERE column1 = 5')

我也不确定调用class.function1.function2是否正确? Django拥有'对象'单词,例如Instance.objects.filter()。排除()

我尝试按如下方式更改代码库:

# database.py

class ModelFactory(object):
    def __init__(self, table):
        self.table = table

    def objects(self):
        def fields(self, **kwargs):
            return self.f(**kwargs)
        def wheres(self, *args):
            return self.w(*args)

    def f(self, *args):
        str_columns = ''
        for count, arg in enumerate(args):
            if count == 0:
                str_columns += arg
            else:
                str_columns += ', %s' % arg
        self.str_columns = str_columns

    def w(self, **kwargs):
        str_wheres = ''
        for count, (key, value) in enumerate(kwargs.items()):
            if count == 0:
                str_wheres += 'WHERE %s = %s' % (key, value)
            else:
                str_wheres += ' AND %s = %s' % (key, value)
        self.str_wheres = str_wheres

但是当我尝试以下内容时:

from database import ModelFactory

myInstance = ModelFactory('myTable')
myQuery = myInstance.objects.fields('column1', 'column2').wheres(column1 = 5)

我得到一个AttributeError:' function'对象没有属性'字段'

2 个答案:

答案 0 :(得分:3)

如果要链接对象的方法调用,则需要从方法返回该对象。即将return self添加到您的方法中。

所以你的类声明可能应该如下所示:

class ModelFactory(object):
    def __init__(self, table):
        self.table = table

    def fields(self, *args):
        self.str_columns = ', '.join(args)
        return self

    def wheres(self, **kwargs):
        str_wheres = ' AND '.join('{} = {}'.format(k, v) for k, v in kwargs.items())
        self.str_wheres = 'WHERE {}'.format(str_wheres)
        return self

    def execute(self):
        // ATTN! This code is prone to SQL injection. Do not use!
        cur.execute('SELECT {columns} FROM {table} {wheres}'.format(columns=self.str_columns, table=self.table, wheres=self.wheres))

答案 1 :(得分:0)

问题是你仍然有objects作为一个功能:

def objects(self):

目前,这意味着您需要将其称为功能 - 您的myQuery行需要看起来像:

myQuery = myInstance.objects().fields(...

但是,由于fieldswheres仅限于objects函数范围内,因此仍然不够。

如果你想要按下这条路线,那么你需要创建一个你在模型中在属性objects下实例化的类 - Django使用QuerySet来实现。如果你看看source,你会看到制作一些东西需要多少魔法"简单"比如objects工作。

这是一个简单的替代方案吗?

您必须创建一个类似于QuerySet的新类,它可以提供fieldswheres可链接功能 - 让我们称之为WernerfeuerSet:< / p>

class WernerfeuerSet:
    def __init__(self, table):
        self.table = table
    def fields(self, **kwargs):
        pass
    def wheres(self, **kwargs):
        pass

现在在你的ModelFactory中实例化 - 比如:

class ModelFactory:
    def __init__(self, table):
        self.objects = WernerfeuerSet(table)

现在您的原始查询应该是可能的,因为objectsModelFactory的属性,而不是函数:

myQuery = myInstance.objects.fields('column1', 'column2').wheres(column1 = 5)