Alexander
You defined __init__ in your mixin and not call base __init__
Lucky
I will rewrite it as one big class.
Alexander
In my test all works as expected:
from pony.orm import *
class PersonMixin(object):
def hello(self):
print('My name is ' + self.name)
class Person(PersonMixin):
def __init__(self, name):
self.name = name
db = Database('sqlite', ':memory:')
class DBPerson(PersonMixin, db.Entity):
name = Required(str)
sql_debug(True)
db.generate_mapping(create_tables=True)
with db_session:
p1 = Person(name='John')
p1.hello()
p2 = DBPerson(name='Mike')
p2.hello()
with db_session:
p3 = select(p for p in DBPerson).first()
p3.hello()
Lucky
Because If you take the DB part away, the Mixin classes alone are very confusing.
Alexander
I think this approach is valid. This way the code may be easier to understand
Lucky
Hey guys
Alexey
hey
Lucky
SELECT DISTINCT ON (m.type) * FROM (
SELECT * FROM DBMessage ORDER BY date DESC
) as m ORDER BY m.type, m.date DESC
This selects the newest (m.date) DBMessage of each m.type in postgres.
Lucky
SELECT * FROM DBmessage ORDER BY date DESC
Lucky
SELECT DISTINCT ON (m.type) * FROM (
SELECT * FROM DBmessage ORDER BY date DESC
) as m ORDER BY m.type, m.date DESC
Lucky
I can't find how to do DISTINCT on pony
Alexey
Is this what you need? https://docs.ponyorm.com/api_reference.html?highlight=distinct#distinct
Lucky
I couldn't find it as I searched :(
Probalby, yes. Thanks
Alexey
there is Quick search field here https://docs.ponyorm.com/toc.html
Alexey
np
Alexander
I think this is not the same thing. As I understand, "DISTINCT ON" is a special PostgreSQL construction which is not equivalent to DISTINCT
Lucky
yeah, DESTINCT and DESTINCT ON ({column}) are different.
https://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-DISTINCT
Alexander
You want to select latest message for each message type
Lucky
DESTINCT removes duplicate rows, DESTINCT ON keeps only the first row with the same value of a column
Lucky
Lucky
Actually I did the wrong thing, here is my correct SQL:
SELECT DISTINCT ON (m.node) * FROM (
SELECT * FROM DBmessage WHERE type = 1
) as m ORDER BY m.node, m.date DESC
But lets stay by the above example :D
Alexander
Can you use max id instead of a latest date to find the latest message? I think it will be a bit easier to write
Lucky
Alexander
ok, with dates you can try the following:
select(m for m in DBMessage if (m.type, m.date) in select((m.type, max(m.date)) for m in DBMessage))
But if two messages of the same type may have indentical date (up to microseconds), you will get both messages
Alexander
Another way is to use raw SQL query:
DBMessage.select_by_sql("""
SELECT DISTINCT ON (m.node) * FROM (
SELECT * FROM DBmessage WHERE type = 1
) as m ORDER BY m.node, m.date DESC
""")
Lucky
Hm, probably a db.select("sql") is better
Lucky
Lucky
Lucky
Btw, how can I apply .show() on the resulting list?
Alexander
Note that inside raw SQL you can use Python expression, which are converted to query parameters:
message_type = 1
DBMessage.select_by_sql("""
SELECT DISTINCT ON (m.node) * FROM (
SELECT * FROM DBmessage WHERE type = $message_type
) as m ORDER BY m.node, m.date DESC
""")
Lucky
Alexander
show is the method of QueryResult. select_by_sql returns list of entities, which don't have show method.
Alexander
Maybe we can add it later
Lucky
Okey, was just to visualize it to myself
Lucky
How would I do m.date >= NOW() - '1 minute'::INTERVAL?
latest_vote = orm.select(m for m in DBVoteMessage).order_by(orm.desc(DBVoteMessage.date)).first()
Lucky
I want to only get messages from the last past hour. Best would be to use the server NOW()
Alexander
You can write
from datetime import datetime, timedelta
select(m for m in DBVoteMessage if m.date >= detetime.now() - timedelta(hours=1))
But Pony will think that expression datetime.now() - timedelta(hours=1) can be evaluated in Python and replaced with a single query parameter.
In order to use server NOW() you can use raw SQL fragment:
select(m for m in DBVoteMessage if m.date >= raw_sql("NOW() - '1 minute'::INTERVAL"))
Lucky
Alexander
Thanks, we'll fix it
Lucky
But raw_sql is very neat.
Is that executed in the same query?
Alexander
yes
Lucky
perfect
Lucky
Alexander
Alexander
oops )
Lucky
:D
Alexey
😄👍
Mikki
Welcome!
HM
Alexey
Lucky
You are the 6th Alexander in this group oO
Rozen
only 6th?
Lucky
I think thats an awful lot 😅
Mikki
Welcome!
Michael
Hey! Thanks :)
Lucky
5
Mikki
Welcome!
stsouko
Hello!
stsouko
from enum import Enum
from pony.orm.dbapiprovider import IntConverter
class EnumConverter(IntConverter):
def validate(self, val):
if not isinstance(val, Enum):
raise ValueError('Must be an Enum. Got {}'.format(type(val)))
return val
def py2sql(self, val):
return val.value
def sql2py(self, val):
return self.py_type(val)
db.provider.converter_classes.append((Enum, EnumConverter))
class Models(db.Entity):
id = PrimaryKey(int, auto=True)
model_type = Required(ModelType, default=ModelType.PREPARING)
class ModelType(Enum):
PREPARER = 0
stsouko
Hello!
stsouko
I tryed to use custom converter.
stsouko
its work if i do smth as: Models[1].model_type
Rozen
use ` to make the code less ugly in the chat
stsouko
but not in queries: select(x.model_type for x in Models)
Rozen
print ('hello wurld')
stsouko
ok
stsouko
`class EnumConverter(IntConverter):
def validate(self, val):
if not isinstance(val, Enum):
raise ValueError('Must be an Enum. Got {}'.format(type(val)))
return val
def py2sql(self, val):
return val.value
def sql2py(self, val):
return self.py_type(val)
db.provider.converter_classes.append((Enum, EnumConverter))`
stsouko
`
class EnumConverter(IntConverter):
def validate(self, val):
if not isinstance(val, Enum):
raise ValueError('Must be an Enum. Got {}'.format(type(val)))
return val
def py2sql(self, val):
return val.value
def sql2py(self, val):
return self.py_type(val)
db.provider.converter_classes.append((Enum, EnumConverter))
`
stsouko
oh sheee
stsouko
http://pastebin.com/yidQy0X6
stsouko
is it possible?
Alexander
Multiline examples are wrapped with three backquotes. What error do you get when using select?
stsouko
TypeError: Unsupported type 'ModelType'
stsouko
select(x.id for x in Models if x.model_type == ModelType.PREPARER)
stsouko
I tryed this and got TypeError: Expression ModelType.PREPARER has unsupported type 'ModelType'
stsouko
если можно на русском, то: я предположил что маппер автоматом раскрывает Енам в число и выполняет запрос. вот и решил сделать так.
Rozen
D:
Alexander
We plan to add support of enums, I think it is a bit more complex than in your example. Right now the simplest you can do is to manualy convert enum items to values inside query:
select(x.id for x in Models if x.model_type == ModelType.PREPARER.value)
stsouko
Thank You for quick response!