Get last insert ID in peewee ORM (python) - python

I would like to retrieve the last insert ID (for use in a second table as a relation), however, I do not know how to get it. I am using the peewee ORM.
The table 'readings' in the database 'nest' has a column 'id' (int (11) auto_increment, primary key).
import time
from peewee import *
database = MySQLDatabase('nest', **{'user': 'nest'})
class Readings(BaseModel):
time = DateTimeField()
class Meta:
db_table = 'readings'
dt = Readings.insert(time=time.strftime("%x %X"))
dt.execute();
print "Last insert id:", dt.last_insert_id(database, Readings);
The last line is where I am stuck. Thanks a lot for your help.

Thank you very much for the the help, the answer was really easy. Here is the correct code:
import time
from peewee import *
database = MySQLDatabase('nest', **{'user': 'nest'})
class Readings(BaseModel):
time = DateTimeField()
class Meta:
db_table = 'readings'
dt = Readings.insert(time=time.strftime("%x %X"))
print "Last insert id: %i" % dt.execute()

You can direct fetch id of that insert record like below
import time
from peewee import *
database = MySQLDatabase('nest', **{'user': 'nest'})
class Readings(BaseModel):
time = DateTimeField()
class Meta:
db_table = 'readings'
dt = Readings(time=time.strftime("%x %X"))
dt.save()
print "Last insert id:"+str(dt.id);

just in case , you can get the id right after insert
huey = User()
huey.username = 'Huey'
huey.save()
huey.id

Python doesn't require semi colons!
Just a note... InsertQuery.execute() should actually return the last insert id. If you want to call last_insert_id() you need to pass in the cursor that was used to execute the query.

Related

Sqlalchemy: how to define constraint newid() for Guid column (mssql)

I want to create a column (Id) of type uniqueidentifier in sqlalchemy in a table called Staging.Transactions. Also, I want the column to automatically generate new guids for inserts.
What I want to accomplish is the following (expressed in sql)
ALTER TABLE [Staging].[Transactions] ADD DEFAULT (newid()) FOR [Id]
GO
The code in sqlalchemy is currently:
from sqlalchemy import Column, Float, Date
import uuid
from database.base import base
from sqlalchemy_utils import UUIDType
class Transactions(base):
__tablename__ = 'Transactions'
__table_args__ = {'schema': 'Staging'}
Id = Column(UUIDType, primary_key=True, default=uuid.uuid4)
AccountId = Column(UUIDType)
TransactionAmount = Column(Float)
TransactionDate = Column(Date)
def __init__(self, account_id, transaction_amount, transaction_date):
self.Id = uuid.uuid4()
self.AccountId = account_id
self.TransactionAmount = transaction_amount
self.TransactionDate = transaction_date
When I create the schema from the python code it does not generate the constraint that I want in SQL - that is - to auto generate new guids/uniqueidentifiers for the column [Id].
If I try to make a manual insert I get error message: "Cannot insert the value NULL into column 'Id', table 'my_database.Staging.Transactions'; column does not allow nulls. INSERT fails."
Would appreciate tips on how I can change the python/sqlalchemy code to fix this.
I've found two ways:
1)
Do not use uuid.uuid4() in init of your table class, keep it simple:
class Transactions(base):
__tablename__ = 'Transactions'
__table_args__ = {'schema': 'Staging'}
Id = Column(String, primary_key=True)
...
def __init__(self, Id, account_id, transaction_amount, transaction_date):
self.Id = Id
...
Instead use it in the creation of a new record:
import uuid
...
new_transac = Transacatins(Id = uuid.uuid4(),
...
)
db.session.add(new_transac)
db.session.commit()
Here, db is my SQLAlchemy(app)
2)
Without uuid, you can use raw SQL to do de job (see SQLAlchemy : how can I execute a raw INSERT sql query in a Postgres database?).
Well... session.execute is a Sqlalchemy solution...
In your case, should be something like this:
table = "[Staging].[Transactions]"
columns = ["[Id]", "[AccountId]", "[TransactionAmount]", "[TransactionDate]"]
values = ["(NEWID(), \'"+str(form.AccountId.data) +"\', "+\
str(form.TransactionAmount.data) +", "+\
str(form.TransactionDate.data))"]
s_cols = ', '.join(columns)
s_vals = ', '.join(values)
insSQL = db.session.execute(f"INSERT INTO {table} ({s_cols}) VALUES {s_vals}")
print (insSQL) # to see if SQL command is OK
db.session.commit()
You have to check where single quotes are really needed.

Peewee query with join doesn't work as expected

I'm new to peewee and currently trying to migrate from normal Python SQlite3 library.
While my code generate a valid SQL query that return result as expected using a SQlite DB browser, trying to get the value of a field return AttributeError: x object has no attribute y.
Model:
class TableShows(BaseModel):
sonarr_series_id = IntegerField(column_name='sonarrSeriesId', unique=True)
title = TextField()
class Meta:
table_name = 'table_shows'
class TableHistory(BaseModel):
sonarr_series_id = ForeignKeyField(TableShows, field='sonarr_series_id', column_name='sonarrSeriesId')
class Meta:
table_name = 'table_history'
Peewee Query:
data = TableHistory.select(
TableShows.title,
TableHistory.sonarr_series_id
).join(
TableShows
).order_by(
TableShows.title.asc()
)
Resulting SQL query:
SELECT "t1"."title", "t2"."sonarrSeriesId"
FROM "table_history" AS "t2"
INNER JOIN "table_shows" AS "t1" ON ("t2"."sonarrSeriesId" = "t1"."sonarrSeriesId")
ORDER BY "t1"."title" ASC
Resulting dicts():
{'title': u'Test title', 'sonarr_series_id': 1}
Why does running this:
for item in data:
print item.title
Return this:
AttributeError: 'TableHistory' object has no attribute 'title'
http://docs.peewee-orm.com/en/latest/peewee/relationships.html#selecting-from-multiple-sources
You access the data via item.sonarr_series_id.title
You might consider naming your fields something a bit more pythonic.

Reverse foreignkey query with peewee

I'm using the peewee orm and I would like to know how to do a reverse foreignkey query.
These are my models:
class Device(BaseModel):
mac = CharField()
ip = CharField()
class Metrics(BaseModel):
device = ForeignKeyField(Device, related_name="metrics")
sensor = CharField()
analog = FloatField(null = True)
timestamp = DateTimeField()
I would like to know the simplest way to get all the Devices that have a Metric with a field sensor="temperature".
I can solve it with various querys and some iteration, but I wonder if there is a more direct way to do it.
Thanks
One way:
Device.select().join(Metric).where(Metric.sensor == 'temperature')
Another way:
Device.select().where(fn.EXISTS(
Metric.select().where((Metric.sensor == 'temperature') & (Metric.device == Device.id))
))

Sql query in django. How to translate?

I have this SQL query:
"INSERT INTO $TABLENAME (address, count) VALUES(%s, %s) \
ON DUPLICATE KEY UPDATE count = VALUES(count) + count"
How to translate it into django ?
I think you're looking for get_or_create https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create
Fore example lets assume $TABLENAME is represented by a django model called MyModel:
models.py:
class MyModel(models.Model):
address = models.CharField(max_length=300, unique=True)
count = models.IntegerField(default=0)
views.py:
new_model, created = MyModel.objects.get_or_create(address="123 1st st")
new_model.count += 1
new_model.save()
get_or_create will either create a new object with the given properties or if it already exists it will return the existing object which you can then update.

SQLite3 OperationalError: Table XYZ has no column named ABC

I am new to peewee, so please forgive me if this is a stupid question. I have searched on Google and in the peewee cookbook, but found no solution so far.
So, I have the following models to four of my DB tables:
class games_def(Model):
id = PrimaryKeyField()
name = TextField()
class Meta:
database = dbmgr.DB
class users_def(Model):
id = PrimaryKeyField()
first_name = TextField()
last_name = TextField()
class Meta:
database = dbmgr.DB
class sessions(Model):
id = PrimaryKeyField()
game = ForeignKeyField(games_def, related_name = 'sessions')
user = ForeignKeyField(users_def, related_name = 'sessions')
comment = TextField()
class Meta:
database = dbmgr.DB
class world_states(Model):
session = ForeignKeyField(sessions)
time_step = IntegerField()
world_state = TextField()
class Meta:
database = dbmgr.DB
Using these models I connect to an SQLite3 DB via peewee, which works fine.
After the connection has been established I do the following in my main Python code:
models.world_states.create(session = 1, time_step = 1)
However, this gives me the following error:
sqlite3.OperationalError: table world_states has no column named session_id
That is basically correct, the table world_state does indeed not contain such a column.
However, I cannot find any reference to "session_id" in my code at all.
Whe does peewee want to use that "session_id" colum name?
Do I miss something essentially here?
When you specify a ForeignKeyField() peewee expects to use a column ending in _id based on their own name. Your wold_states.session field thus results in an column named session_id.
You can override this by setting db_column for that field:
class world_states(Model):
session = ForeignKeyField(sessions, db_column='session')

Categories