Почему Peewee не заполняет идентификатор моего объекта? - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь создать драйвер базы данных для Peewee, и у меня возникают проблемы с получением метода save() для заполнения первичного ключа / идентификатора для объектов. Вот пример кода:

from datetime import date
from peewee import BooleanField
from peewee import CharField
from peewee import DateField
from peewee import ForeignKeyField
from peewee import IntegerField
from peewee import Model
from SQLRelay import PySQLRDB
from sqlrelay_ext import SQLRelayDatabase

DB = SQLRelayDatabase('test2', host='<host>', user='<un>', password='<pwd>')

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

class Person(BaseModel):
    name = CharField()
    birthday = DateField()
    is_relative = BooleanField()

class Pet(BaseModel):
    owner = ForeignKeyField(Person, backref='pets')
    name = CharField()
    animal_type = CharField()

DB.connect()
Person.create_table(safe=False)
Pet.create_table(safe=False)
uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15), is_relative=True)
uncle_bob.save() # bob is now stored in the database
print('Uncle Bob id: {}'.format(uncle_bob.id))
print('Uncle Bob _pk: {}'.format(uncle_bob._pk))

И uncle_bob.id, и uncle_bob._pk равны None после .save(). При копании в коде peewee.py кажется, что метод _WriteQuery.execute() должен установить атрибут _pk, но этого не происходит. Я думаю, что реализация курсора не работает должным образом. У кого-нибудь есть более проницательное понимание, чем это, которое может помочь мне отследить эту проблему?

Спасибо!

Изменить, чтобы ответить:

Для SQL Server следующий код позволяет вернуть последний вставленный идентификатор:

def last_insert_id(self, cursor, query_type=None):
    try:
        cursor.execute('SELECT SCOPE_IDENTITY()')
        result = cursor.fetchone()
        return result[0]
    except (IndexError, KeyError, TypeError):
        pass

1 Ответ

0 голосов
/ 10 мая 2018

В вашей реализации SQLRelayDatabase вам, вероятно, потребуется правильно реализовать метод last_insert_id(). Для драйверов python db-api 2.0 это обычно выглядит как cursor.lastrowid.

Реализация по умолчанию:

def last_insert_id(self, cursor, query_type=None):
    return cursor.lastrowid

Где cursor - объект курсора, используемый для выполнения запроса вставки.

Базы данных, такие как Postgresql, не реализуют это - вместо этого вы выполняете запрос INSERT ... RETURNING, поэтому реализация Postgres немного отличается. Реализация postgres гарантирует, что ваш запрос вставки включает в себя предложение RETURNING, а затем получает возвращенный идентификатор.

В зависимости от вашей БД и используемого драйвера БД, вам нужно каким-то образом извлечь последний идентификатор вставки. Peewee должен обрабатывать все остальное, если last_insert_id() реализовано.

...