如何在 Elixir/SqlAlchemy 中创建类属性和类属性

发布于 2024-12-09 11:10:25 字数 3073 浏览 4 评论 0原文

我有一个类:

from sys import stderr
from elixir import *
from types import *

class User(Entity):
    using_options(tablename="users")
    first_name = Field(String(50))
    middle_name = Field(String(50))
    last_name = Field(String(50))

    def __get_name__ (self):
        first_name = self.first_name if self.first_name is not None else ""
        middle_name = self.middle_name if self.middle_name is not None else ""
        last_name = self.last_name if self.last_name is not None else ""
        return " ".join((first_name, middle_name, last_name)).strip()

    def __set_name__ (self,string):
        first_name = ""
        middle_name = ""
        last_name = ""
        split_string = string.split(' ')
        if len(split_string) == 1:
            first_name = string
        elif len(split_string) == 2:
            first_name, last_name = split_string
        elif len(split_string) == 3:
            first_name, middle_name, last_name = split_string
        else: #len(split_string) > 3:
            first_name = split_string[0]
            last_name = split_string[-1]
            middle_name = " ".join(split_string[1:-2])
        self.first_name = first_name
        self.middle_name = middle_name
        self.last_name = last_name

    name = property(__get_name__,__set_name__)

我想运行一个查询,如下所示:

def get_user(user):
    found = None
    if type(user) in [IntType,StringType]:
        if type(user) is StringType:
            where = or_(User.first_name==user,
                        User.middle_name==user,
                        User.last_name==user,
                        User.name==user)
            qry = User.query.filter(where)
        elif type(user) is IntType:
            where = or_(User.id==user,
                        User.employee_id==user)
            qry = User.query.filter(where)
        try:
            found = qry.one()
        except NoResultFound:
            print >> stderr, "Couldn't find '%s'" % user
    elif type(user) == User:
        found=user
    return found

但是,生成的 SQL 查询如下所示:

SELECT users.first_name AS users_first_name, 
       users.middle_name AS users_middle_name, 
       users.last_name AS users_last_name
FROM users 
WHERE users.first_name = 'Joseph'
   OR users.middle_name = 'M'
   OR users.last_name = 'Schmoe'
   OR false

请注意“false”代替了 User.name 字段。

我收到此错误:

sqlalchemy.exc.OperationalError: (OperationalError) no such column: false 

我认为我希望 SQL 查询如下所示:

SELECT users.name
FROM users 
WHERE users.name = 'Joseph M Schmoe'

编辑:所需/第二个 SQL 查询与我真正想要的不正确:某种创建“名称”的被动方式数据库中的字段对应于“first_name”、“middle_name”、“last_name”的串联。

Edit2:我相信以下内容将使我几乎到达目的地。然而,我仍然在努力寻找正确的表达方式。

Edit3:看起来它适合我需要它做的事情。所以我将其作为答案。

I have a class:

from sys import stderr
from elixir import *
from types import *

class User(Entity):
    using_options(tablename="users")
    first_name = Field(String(50))
    middle_name = Field(String(50))
    last_name = Field(String(50))

    def __get_name__ (self):
        first_name = self.first_name if self.first_name is not None else ""
        middle_name = self.middle_name if self.middle_name is not None else ""
        last_name = self.last_name if self.last_name is not None else ""
        return " ".join((first_name, middle_name, last_name)).strip()

    def __set_name__ (self,string):
        first_name = ""
        middle_name = ""
        last_name = ""
        split_string = string.split(' ')
        if len(split_string) == 1:
            first_name = string
        elif len(split_string) == 2:
            first_name, last_name = split_string
        elif len(split_string) == 3:
            first_name, middle_name, last_name = split_string
        else: #len(split_string) > 3:
            first_name = split_string[0]
            last_name = split_string[-1]
            middle_name = " ".join(split_string[1:-2])
        self.first_name = first_name
        self.middle_name = middle_name
        self.last_name = last_name

    name = property(__get_name__,__set_name__)

I'd like to run a query as follows:

def get_user(user):
    found = None
    if type(user) in [IntType,StringType]:
        if type(user) is StringType:
            where = or_(User.first_name==user,
                        User.middle_name==user,
                        User.last_name==user,
                        User.name==user)
            qry = User.query.filter(where)
        elif type(user) is IntType:
            where = or_(User.id==user,
                        User.employee_id==user)
            qry = User.query.filter(where)
        try:
            found = qry.one()
        except NoResultFound:
            print >> stderr, "Couldn't find '%s'" % user
    elif type(user) == User:
        found=user
    return found

However, the resultant SQL query looks something like the following:

SELECT users.first_name AS users_first_name, 
       users.middle_name AS users_middle_name, 
       users.last_name AS users_last_name
FROM users 
WHERE users.first_name = 'Joseph'
   OR users.middle_name = 'M'
   OR users.last_name = 'Schmoe'
   OR false

Notice the 'false' in place of the User.name field.

I'm getting this error:

sqlalchemy.exc.OperationalError: (OperationalError) no such column: false 

I think what I'd like the SQL query to look like is the following:

SELECT users.name
FROM users 
WHERE users.name = 'Joseph M Schmoe'

Edit: The desired/second SQL query was incorrect for what I really wanted: some sort of passive way to create a 'name' field within the database which corresponds to a concatenate of 'first_name','middle_name','last_name'.

Edit2: I believe that the following will get me almost there. However, I'm still struggling with the proper expression.

Edit3: Looks like it works for what I need it to do. So I'm including it as the answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

两个我 2024-12-16 11:10:25

您定义了属性,该属性将在分配对象后可用。

注意:为了方便,我更改了您的代码

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, DateTime, String
from datetime import datetime

Base = declarative_base()
class User(Base):
    first_name = Column('first_name', String)
    middle_name = Column('middle_name', String)
    last_name = Column('last_name', String)

    def __get_name__ (self):
        first_name = self.first_name if self.first_name is not None else ""
        middle_name = self.middle_name if self.middle_name is not None else ""
        last_name = self.last_name if self.last_name is not None else ""
        return " ".join((first_name, middle_name, last_name)).strip()

    def __set_name__ (self,string):
        first_name = ""
        middle_name = ""
        last_name = ""
        split_string = string.split(' ')
        if len(split_string) == 1:
            first_name = string
        elif len(split_string) == 2:
            first_name, last_name = split_string
        elif len(split_string) == 3:
            first_name, middle_name, last_name = split_string
        else: #len(split_string) > 3:
            first_name = split_string[0]
            last_name = split_string[-1]
            middle_name = " ".join(split_string[1:-2])
        self.first_name = first_name
        self.middle_name = middle_name
        self.last_name = last_name

    name = property(__get_name__,__set_name__)

因此,first_name、middle_name 和 last_name 是类属性。当您定义属性时,它需要该对象的实例。

In [13]: User.first_name
Out[13]: Column('first_name', String(), )

In [14]: User.name
Out[14]: <property object at 0x26fef70>

在上面的示例中您可以看到差异。在您设置该属性或该属性的任何字段之前,它将始终为空。

您必须给予

In [16]: u1 = User()

In [17]: u1.name = "first middle last"

In [18]: u1.name
Out[18]: 'first middle last'

In [19]: u1.first_name
Out[19]: 'first'

之后您才能使用财产。

这将帮助您理解您的问题。 您的属性与实例关联,您无法按类访问它。

You are define the property and that will be available after object will be assign.

Note : I change your code for my convenience

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, DateTime, String
from datetime import datetime

Base = declarative_base()
class User(Base):
    first_name = Column('first_name', String)
    middle_name = Column('middle_name', String)
    last_name = Column('last_name', String)

    def __get_name__ (self):
        first_name = self.first_name if self.first_name is not None else ""
        middle_name = self.middle_name if self.middle_name is not None else ""
        last_name = self.last_name if self.last_name is not None else ""
        return " ".join((first_name, middle_name, last_name)).strip()

    def __set_name__ (self,string):
        first_name = ""
        middle_name = ""
        last_name = ""
        split_string = string.split(' ')
        if len(split_string) == 1:
            first_name = string
        elif len(split_string) == 2:
            first_name, last_name = split_string
        elif len(split_string) == 3:
            first_name, middle_name, last_name = split_string
        else: #len(split_string) > 3:
            first_name = split_string[0]
            last_name = split_string[-1]
            middle_name = " ".join(split_string[1:-2])
        self.first_name = first_name
        self.middle_name = middle_name
        self.last_name = last_name

    name = property(__get_name__,__set_name__)

So first_name, middle_name and last_name are Class attributes. When you define property it needs instance of that object.

In [13]: User.first_name
Out[13]: Column('first_name', String(), )

In [14]: User.name
Out[14]: <property object at 0x26fef70>

In the above example you can see the difference. Until you will set that property or any fields of that property it will be always empty.

You have to give

In [16]: u1 = User()

In [17]: u1.name = "first middle last"

In [18]: u1.name
Out[18]: 'first middle last'

In [19]: u1.first_name
Out[19]: 'first'

After this you can use property.

This will help you to understand your problem. Your property is associated with instance you cant access it by class.

不寐倦长更 2024-12-16 11:10:25
from sqlalchemy.ext.hybrid import hybrid_property

@hybrid_property
def name (self):
    first_name = self.first_name if self.first_name is not None else ""
    middle_name = self.middle_name if self.middle_name is not None else ""
    last_name = self.last_name if self.last_name is not None else ""
    return " ".join((first_name, middle_name, last_name)).strip()

@name.setter
def name (self,string):
    first_name = ""
    middle_name = ""
    last_name = ""
    split_string = string.split(' ')
    if len(split_string) == 1:
        first_name = string
    elif len(split_string) == 2:
        first_name, last_name = split_string
    elif len(split_string) == 3:
        first_name, middle_name, last_name = split_string
    else: #len(split_string) > 3:
        first_name = split_string[0]
        last_name = split_string[-1]
        middle_name = " ".join(split_string[1:-2])
    self.first_name = first_name
    self.middle_name = middle_name
    self.last_name = last_name

表达式部分在这里:

@name.expression
def name (cls):
    f = cls.first_name
    m = cls.middle_name
    l = cls.last_name
    return f+' '+m+' '+l
from sqlalchemy.ext.hybrid import hybrid_property

@hybrid_property
def name (self):
    first_name = self.first_name if self.first_name is not None else ""
    middle_name = self.middle_name if self.middle_name is not None else ""
    last_name = self.last_name if self.last_name is not None else ""
    return " ".join((first_name, middle_name, last_name)).strip()

@name.setter
def name (self,string):
    first_name = ""
    middle_name = ""
    last_name = ""
    split_string = string.split(' ')
    if len(split_string) == 1:
        first_name = string
    elif len(split_string) == 2:
        first_name, last_name = split_string
    elif len(split_string) == 3:
        first_name, middle_name, last_name = split_string
    else: #len(split_string) > 3:
        first_name = split_string[0]
        last_name = split_string[-1]
        middle_name = " ".join(split_string[1:-2])
    self.first_name = first_name
    self.middle_name = middle_name
    self.last_name = last_name

The Expression part is here:

@name.expression
def name (cls):
    f = cls.first_name
    m = cls.middle_name
    l = cls.last_name
    return f+' '+m+' '+l
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文