为什么Peewee在MySQL的选择查询中包含“id”列?

13

我正在尝试学习如何在mysql中使用peewee。

我已经有一个存在于mysql服务器上的数据库,并且有一张已存在的表。目前这个表是空的(我只是在进行测试)。

>>> db = MySQLDatabase('nhl', user='root', passwd='blahblah')
>>> db.connect()


>>> class schedule(Model):
...     date = DateField()
...     team = CharField()
...     class Meta:
...             database = db

>>> test = schedule.select()
>>> test
<class '__main__.schedule'> SELECT t1.`id`, t1.`date`, t1.`team` FROM `nhl` AS t1 []
>>> test.get()
我遇到了以下错误:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/site-packages/peewee.py", line 1408, in get
    return clone.execute().next()
  File "/usr/lib/python2.6/site-packages/peewee.py", line 1437, in execute
    self._qr = QueryResultWrapper(self.model_class, self._execute(), query_meta)
  File "/usr/lib/python2.6/site-packages/peewee.py", line 1232, in _execute
    return self.database.execute_sql(sql, params, self.require_commit)
  File "/usr/lib/python2.6/site-packages/peewee.py", line 1602, in execute_sql
    res = cursor.execute(sql, params or ())
  File "/usr/lib64/python2.6/site-packages/MySQLdb/cursors.py", line 201, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib64/python2.6/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1054, "Unknown column 't1.id' in 'field list'")
为什么peewee将'id'列添加到选择查询中?我在已经存在于数据库中的表中没有id列。我只想使用现有的表而不依赖于每次与数据库交互时peewee创建一个新的表。这就是我认为错误所在的地方。
查询的结果应该为空,因为表是空的,但由于我正在学习,我只想尝试一下代码。感谢您的帮助。
编辑
根据Wooble和Francis的有益回答,我开始思考是否使用peewee或类似于sqlalchemy的ORM甚至有意义。使用ORM而不是仅使用MySQLdb在Python中运行直接查询的好处是什么?
这是我期望做的事情:
- 从各种Web服务器自动下载数据。大多数数据都以xls或csv格式提供。我可以使用xlrd包将xls转换为csv。 - 在插入/批量插入到mysql db表之前,在列表对象中解析/处理数据。 - 运行复杂的查询,将数据从mysql导出到python中,以适当的数据结构(例如,列表)进行各种统计计算,在python中更容易进行而不是在mysql中。任何可以在mysql中完成的都将在那里完成,但我可能会在python中运行复杂的回归分析。 - 运行各种图形包以对从查询检索的数据进行操作。其中一些可能包括使用R-project的ggplot2软件包,这是一个高级图形软件包。因此,我将涉及一些R / Python集成。
考虑到上述情况,最好花费几个小时来学习ORM/Peewee/SQLAlchemy还是坚持使用MySQLdb进行直接mysql查询?
4个回答

18
大多数简单的活动记录模式ORM需要一个id列来跟踪对象身份。PeeWee似乎是其中之一(或者至少我不知道任何不使用id的方法)。您可能无法在不修改数据表的情况下使用PeeWee。
您现有的数据表似乎设计得不太好,因为它似乎缺少关键字或组合关键字。每个数据表都应该有一个关键属性,否则就无法区分一行与另一行。
如果其中一个列是主键,请尝试添加一个“primary_key=True”参数,如在非整数主键方面的文档中所述
date = DateField(primary_key=True)

如果您的主键不是命名为id,那么您必须在peewee模型中将表的实际主键设置为"PrimaryKeyField()"类型。

您应该研究SQLAlchemy,它使用数据映射器模式。它更加复杂,但也更加强大。它不会对您的SQL表设计施加任何限制,事实上,在大多数情况下,它可以自动反映您的表结构和相互关系。(可能在MySQL中不太好,因为外键关系在默认表引擎中不可见。)最重要的是,它可以处理缺乏键的表。


1
感谢您详细的回复。事实证明,数据库中现有的表确实有一个主键(日期)。我需要像Wooble所指示的那样使用pwiz来将此信息提供给peewee吗?感谢您的帮助。 - codingknob
你并不需要使用pwiz,因为它只是一个代码生成器,而且没有任何你自己不能做的事情。你只需像描述非整数主键的文档中所解释的那样包含 primary_key=True 参数即可。 - Francis Avila
我正在调研SQLAlchemy,因为Peewee将来不能满足我的需求。 - codingknob
1
很抱歉听到Peewee不能满足您的需求 - 如果您能提供任何建议或我可以改进它的事情,我将不胜感激。 - coleifer
这个方法对我有效,同时不要把primary_key和unique混淆,如果你是数据库新手的话。 - OzzyTheGiant

11
如果您的主键列名不是'id',则应该在该表模型类中添加额外的字段:
class Table(BaseModel):
    id_field = PrimaryKeyField()

这将告诉您的脚本,您的表在名为"id_field"的列中保存了主键,并且该列是启用自动递增的INT类型。 这里是描述peewee字段类型的文档。

如果您想对主键字段进行更多控制,如Francis Avila所指出的,创建字段时应使用primary_key=True参数:

class Table(BaseModel):
    id_field = CharField(primary_key=True)

请查看这个链接,了解非整数主键文档。


3

你需要为这个模型提供一个主键字段。 如果你的表没有单个主键字段(就像我的一样),在Meta中定义的复合主键会有帮助。

primary_key = peewee.CompositeKey('date', 'team')

我已经更新了答案,现在很清楚了。刚刚找到了一种制作CompositeKey的方法。 - ySJ

0

在调用select()方法之前,您需要使用peewee的create table方法创建实际的数据库表,该方法将在表中创建一个id列。


这会在我的实际数据库中创建表吗?我已经在数据库中有了那个表。我很困惑,因为Peewee文档对新手不太友好。 - codingknob
还有,是否有一份逐步指南/示例,说明如何执行以下操作:a)连接到数据库,b)将存储在列表对象中的记录插入表中,c)执行复杂查询(包含连接、分组等),d)将查询结果存储在 Python 列表对象中,以供其他用途使用。Peewee 文档没有充分解释该软件包的最终用例,以及如何按照我所描述的从 a 到 d 的工作流程进行操作。 - codingknob
每个模型都有一个 create_table() 类方法,它在数据库中运行 CREATE TABLE 语句。它将创建表格,包括所有列、外键约束和索引。通常这只是在添加新模型时执行一次。但是,如果要使用现有表格,则需要手动创建模型字段与表格列之间的映射关系。希望能帮到你。 - codingknob
请查看http://peewee.readthedocs.org/en/latest/peewee/quickstart.html#do-you-have-a-legacy-database,你需要使用`pwiz`实用程序为传统数据库生成模型;默认用法是定义模型并让框架处理数据库端。 - Wooble
谢谢你的回复,Wooble!我会看一下。不过,我对原帖进行了编辑,并提出了一个后续问题,如果你有任何指导,我将不胜感激。谢谢。 - codingknob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接