0

这是我的用户对象

class User(BaseModel):

    _email = CharField(max_length=255, unique=True)
    _first_name = CharField(max_length=255)
    _last_name = CharField(max_length=255)
    _profile_image = CharField(max_length=500, default=None)
    _gender = CharField(max_length=255, default=None)

    def __init__(self, email, first_name, last_name):
        self._email = email
        self._first_name = first_name
        self._last_name = last_name
        self._profile_image = None
        self._gender = None
    def serialize(self):
       user_map = {}
       for attr, value in self.__dict__.items():
          user_map[attr[1:]] = value
       return user_map

这是 BaseModel 对象

class BaseModel(Model):
    _create_at = DateTimeField(default=datetime.now())
    _modified_at = DateTimeField(default=datetime.now())

    class Meta:
        database = db

这就是数据库的定义方式,

db = SqliteDatabase('cmp_v0.db')


def before_request_handler():
    db.connect()


def after_request_handler():
    db.close()

这是用户资源,

class UserResource:
    def on_get(self, req, res):
        user = User('someone@email.com', 'Firstname', 'Lastname')
        res.body = json.dumps(user.serialize())

这是创建 REST 端点的代码

api = falcon.API()
api.add_route('/user', UserResource())

当我转到网址http://127.0.0.1:8000/user时 ,我收到以下错误,

instance._data[self.att_name] = value
TypeError: 'NoneType' object does not support item assignment

我究竟做错了什么。

4

1 回答 1

1

您看到的错误来自User将值分配给 , 等的构造函数_email_first_name这些是您的字段定义,不要将数据分配给这些名称 - 您应该使用相同的名称但前面没有下划线。

当您设置诸如_email覆盖字段定义之类的设置时,Peewee 会感到非常困惑,因为当您尝试设置实例值时,它期望使用的字段定义已经消失。

所以这个构造函数有效:

class User(BaseModel):

    _email = CharField(max_length=255, unique=True)
    _first_name = CharField(max_length=255)
    _last_name = CharField(max_length=255)
    _profile_image = CharField(max_length=500, default=None)
    _gender = CharField(max_length=255, default=None)

    def __init__(self, email, first_name, last_name):
        self.email = email # note the lack of underscores
        self.first_name = first_name
        self.last_name = last_name
        self.profile_image = None
        self.gender = None

作为旁注,您的serialize方法也存在问题,因为它输出 JSON 如下:

{"mail": "someone@email.com", "irst_name": "Firstname",
 "rofile_image": null, "ast_name": "Lastname", "ender": null}

而我认为你想要这个:

{"gender": null, "first_name": "Firstname", 
 "last_name": "Lastname", "profile_image": null, "email": "someone@email.com"}

代码是这样的:

     def serialize(self):
       user_map = {}
       for attr, value in self.__dict__.items():
          user_map[attr] = value # note the change here
       return user_map

Annnd 最后:通过覆盖而__init__不是调用超类(你的BaseModel)你没有得到你的._create_at_modified_atUserModel

为此,您需要执行以下操作:

        def __init__(self, email, first_name, last_name):
            super(User,self).__init__()
            self.email = email

但后来我发现你的serialize功能停止工作 - 但是,最初的问题解决了!

更新

我回顾了 Peewee 的文档,包括它的Quickstart,并决定有一个更好的方法来做到这一点:根本不使用自定义构造函数。

下面的代码功能齐全,避免了自定义构造函数。它不会在 Falcon 中包含任何内容,因为它与问题无关并使其更简单。

from datetime import datetime
from peewee import *

db = SqliteDatabase('cmp_v0.db')
db.connect()


class BaseModel(Model):
    created_at = DateTimeField(default=datetime.now())
    modified_at = DateTimeField(default=datetime.now())

    class Meta:
        database = db


class User(BaseModel):

    # These are
    email = CharField(max_length=255, unique=True)
    first_name = CharField(max_length=255)
    last_name = CharField(max_length=255)
    profile_image = CharField(max_length=500, default=None)
    gender = CharField(max_length=255, default=None)

    def serialize(self):
        user_map = {}
        for attr, value in self.__dict__.items():
            user_map[attr] = value
        return user_map

db.create_tables([User], safe=True)

user_row_count = len(User.select())
user = User(email='someone{}@example.com'.format(user_row_count+1),
            first_name='Firstname',
            last_name='Lastname',
            profile_image='',
            gender='')

print 'User {} {} {}'.format(user.email, user.first_name, user.last_name)
print 'Timestamps {} {}'.format(user.created_at,
                                user.modified_at)
user.save()

通过 Python 和 Peewee 的魔力,这一切都有效。

我没有读过 Peewee 的源代码,但它会遵循一个熟悉的模式:

字段声明即CharField是类级别的;如果你User使用 ipython 之类的东西检查类,你会看到它User.first_name存在。

当创建一个新User的时,Peewee 将在后台处理构造并生成一个实例,该实例通过 Python和User拦截属性值的所有读/写。__getattr____setattr__

当一个User实例save()被调用时,它可能会使用类级别的字段声明来验证和构造要保存的 SQL 查询。

于 2017-05-18T11:27:03.670 回答