首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Peewee成功创建了新条目,但从select()查询中丢失了外键值

Peewee成功创建了新条目,但从select()查询中丢失了外键值
EN

Stack Overflow用户
提问于 2019-09-11 05:03:34
回答 1查看 240关注 0票数 0

Python版本3.6.8,peewee版本3.10.0

我使用peewee在sqlite数据库中设置了3个表。

代码语言:javascript
复制
Plan:
- id : int (primary key)
- plan_name : varchar (unique)
- status : int (foreign key for PlanStatus)
- category : int (foreign key for PlanCategory)

PlanStatus:
- id : int (primary key)
- value : varchar (unique)

PlanCategory:
- id : int (primary key)
- value : varchar (unique)

PlanStatus是一个枚举引用表,PlanCategory是另一个枚举引用表。在下面的代码中,PlanStatus是用许多样板实现的,每个枚举表都必须重复这些样板。相反,PlanCategory继承自父类EnumBaseModel,包括两个类方法。目标是通过继承来减少样板文件。

结果是两个枚举表都被成功填充,您可以通过查询访问它们的值。但是,在创建计划条目时,会在数据库中添加一行(在sqlite中检查),但是select查询会返回缺少PlanCategory外键的行。

创建表和添加行:

代码语言:javascript
复制
from peewee import *

DATABASE = SqliteDatabase('test.db')

# Base class with the inner Meta class defined
class BaseModel(Model):
    class Meta:
        database = DATABASE

# PlanStatus class, used with the following 2 methods
class PlanStatus(BaseModel):
    value = CharField(unique=True)

# Helper function for PlanStatus
def init_plan_status_values(values):
    for value in values:
        if not PlanStatus.select().where(PlanStatus.value == value).exists():
            PlanStatus.create(value=value)

# Helper function for PlanStatus
def get_plan_status(value):
    try:
        return PlanStatus.get(PlanStatus.value == value)
    except DoesNotExist as err:
        return None

# Base class with 2 classmethods
class EnumBaseModel(BaseModel):
    value = CharField(unique=True)

    @classmethod
    def init_values(cls, values):
        for value in values:
            if not cls.select().where(cls.value == value).exists():
                cls.create(value=value)

    @classmethod
    def get(cls, value):
        try:
            return cls.select().where(cls.value == value).get()
        except DoesNotExist as err:
            return None

# PlanCategory inherits EnumBaseModel class and its 2 classmethods
class PlanCategory(EnumBaseModel):
    pass

# Plan has 2 foreign keys
class Plan(BaseModel):
    plan_name = CharField(unique=True)
    status = ForeignKeyField(model=PlanStatus, backref='plans')
    category = ForeignKeyField(model=PlanCategory, backref='plans')

DATABASE.connect()
DATABASE.create_tables(
    [
        PlanStatus,
        PlanCategory,
        Plan
    ],
    safe=True
)

# Populating the enum values PlanStatus the explicit way above
init_plan_status_values(('STATUS-1', 'STATUS-2', 'STATUS-3'))

# Find status_2 the explicit way above
status_2 = get_plan_status('STATUS-2')

# Populating the enum values in PlanCategory using the inherited classmethod above
PlanCategory.init_values(('CATEGORY-1', 'CATEGORY-2', 'CATEGORY-3'))

# Find category_3 using the inherited classmethod above
category_3 = PlanCategory.get('CATEGORY-3')

# Add one plan
try:
    Plan.create(
        plan_name='not bad plan',
        status=status_2,
        category=category_3,
    )
except IntegrityError as err:
    print(err)

现在,我们可以看到在sqlite3中成功添加了行:

代码语言:javascript
复制
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .tables
plan          plancategory  planstatus
sqlite> select * from planstatus;
1|STATUS-1
2|STATUS-2
3|STATUS-3
sqlite> select * from plancategory;
1|CATEGORY-1
2|CATEGORY-2
3|CATEGORY-3
sqlite> select * from plan;
1|not bad plan|2|3
sqlite>

现在检查select()查询中的计划条目,'a_plan.status‘是有效的,但是'a_plan.category’是None。

代码语言:javascript
复制
# We see the references status_2 and category_3 are valid
print('status_2 = ', type(status_2), status_2, status_2.value)
print('category_3 = ', type(category_3), category_3, category_3.value)
print()

# We check the one plan in the table and see now the foreign-key value "category" is missing
a_plan = Plan.get()
print('a_plan: plan_name={}, status={}, category={}'.format(
    a_plan.plan_name,
    a_plan.status,
    a_plan.category
))
print()

打印结果:

代码语言:javascript
复制
status_2 =  <Model: PlanStatus> 2 STATUS-2
category_3 =  <Model: PlanCategory> 3 CATEGORY-3

a_plan: plan_name=not bad plan, status=2, category=None

此外,我还找到了peewee创建的属性'status_id‘和'category_id’。至少'category_id‘仍然保留外键int值。

代码语言:javascript
复制
# After inspecting dir(a_plan), found these attributes:
print('status = ', type(a_plan.status), a_plan.status)
print('status_id = ', type(a_plan.status_id), a_plan.status_id)
print('category = ', type(a_plan.category), a_plan.category)
print('category_id = ', type(a_plan.category_id), a_plan.category_id)

打印结果:

代码语言:javascript
复制
status =  <Model: PlanStatus> 2
status_id =  <class 'int'> 2
category =  <class 'NoneType'> None
category_id =  <class 'int'> 3

有没有办法解决这个问题,这样它就可以解决'a_plan.category‘了?

EN

回答 1

Stack Overflow用户

发布于 2019-09-11 05:24:01

您正在覆盖Peewee使用的方法(.get)。别干那事!我认为你把事情搞得太神奇了(并且在这个过程中到处都引入了查询)。

试着简化一下。我几乎可以保证问题出在你对Peewee依赖的类方法所做的重写中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57878188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档