尝试使用 Peewee 输入 ForeignKey 字段时出现 AttributeError

AttributeError when attempting to enter ForeignKey fields with Peewee

我真的很费时间试图找出我收到的错误消息的原因。

我正在编写一个网络抓取工具,使用 Python 将数据从 Procycing Stats 抓取到 MySQL 数据库中,使用 BeautifulSoup 进行抓取,使用 Peewee 进行数据库交互。网络抓取工具工作得很好,但我在将数据插入 MySQL tables.

时遇到了一些麻烦

首先,我使用 peewee 的 create_tables() 函数在空数据库中创建了 table。在下面,我粘贴了我的 Peewee 模型的代码,该代码包含在我称为 peewee_lib.py 的文件中。

from peewee import *
from mysql_login_info import *

results_database = MySQLDatabase(mysql_db_name, user=mysql_uname, password=mysql_pw, host='localhost')

class BaseModel(Model):
    class Meta:
        database = results_database

class Rider(BaseModel):

    pcsid = IntegerField()
    name = CharField()

class Race(BaseModel):

    name = CharField()

class Result(BaseModel):

    name = CharField()
    year = IntegerField()
    date = DateField()

    position = IntegerField()
    points_pcs = IntegerField()

    race = ForeignKeyField(Race, backref='results')
    rider = ForeignKeyField(Rider, backref='results')

接下来,我使用一个文件 scrape_to_peewee.py 创建 class 那些 "bind" 我的 class 从我的抓取库 scraper_lib.py 和前面提到的定义peewee 图书馆,peewee_lib.py

这是来自 scrape_to_peewee.py 的代码:

import scraper_lib as pylib
import peewee_lib as pw

class Sheet_bind:

    def __init__(self, rider_obj, sheet):

        self.year = sheet.year
        self.rider = sheet.rider
        self.rows = []

        for row in sheet.rows:

            if row.row_type == "tour_header":
                pass
            else:
                temp_query = pw.Race.select().where(pw.Race.name == row.race)
                if not temp_query.exists():
                    temp_query = pw.Race(name=row.race)
                    temp_query.save()
                else:
                    pass

                temp_res = pw.Result(name=row.name,\
                                  year=sheet.year,\
                                  position=row.result,\
                                  points_pcs=row.points_pcs)



                if row.row_type in ["stage", "classification"]:
                    temp_res.name = row.race + ' ' + row.name
                temp_res.race=temp_query
                temp_res.rider=rider_obj
                temp_res.save()
            temp_query = None
            temp_res = None


class Rider_bind:

    def __init__(self, rider_id):

        self.rider_py = pylib.Rider(rider_id)
        self.rider_pw = pw.Rider(pcsid=self.rider_py.url_id, name=self.rider_py.name)
    self.rider_pw.save()


    def load_sheets(self, start_year, end_year):

        for year in xrange(start_year, end_year + 1):
            if year not in self.rider_py.sheets:
                self.rider_py.load_sheets(year, year)

            loaded_sheet = Sheet_bind(self.rider_pw, self.rider_py.sheets[year])
            loaded_sheet.save() 



def main():
    pw.results_database.connect()

main()

将这个最终文件加载到解释器中后,我尝试将示例车手加载到数据库中。启动 Rider_bind class 工作正常,我仔细检查以确保一行实际上已写入 MySQL 中的 rider table,它有。但是,当我尝试使用 Rider_bind.load_sheets() 将结果加载到数据库中时,出现以下错误:

$ python
Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scrape_to_peewee import *
>>> olly = Rider_bind("oliver-naesen")
>>> olly.load_sheets(2018, 2018)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "scrape_to_peewee.py", line 55, in load_sheets
    loaded_sheet = Sheet_bind(self.rider_pw, self.rider_py.sheets[year])
  File "scrape_to_peewee.py", line 33, in __init__
    temp_res.race=temp_query
  File "/home/trenza/.local/lib/python2.7/site-packages/peewee.py", line 3848, in __set__
    if obj != fk_value and self.name in instance.__rel__:
  File "/home/trenza/.local/lib/python2.7/site-packages/peewee.py", line 726, in __ne__
    return not (self == other)
  File "/home/trenza/.local/lib/python2.7/site-packages/peewee.py", line 723, in __eq__
    return self._hash == other._hash
AttributeError: 'NoneType' object has no attribute '_hash'

问题似乎与将其中一个 peewee 模型分配给外键字段有关。当我颠倒调用顺序以便 temp_res.rider = rider_obj 排在第一位时,它给了我同样的错误,回溯指向该调用。

从 peewee 文档看来,ForeignKey 字段应该像将另一个 peewee class 作为值分配给它们一样简单。有谁知道我在这里弄错了什么?任何帮助将非常感激。

谢谢!

编辑:

不是 this question 的副本,因为它(据我所知)与 select 调用中的 return 值无关(上述问题中的问题) .

分配给属性时,您需要将 "temp_query" 解析为对象。

            if not temp_query.exists():
                temp_query = pw.Race(name=row.race)
                temp_query.save()
            else:
                temp_query = temp_query.get()  # fixed.