Czy istnieje prosty sposób na iterację par nazw kolumn i wartości?
Moja wersja sqlalchemy to 0.5.6
Oto przykładowy kod, w którym próbowałem użyć dict (wiersz), ale zgłasza wyjątek, TypeError: Obiekt „User” nie jest iterowalny
import sqlalchemy
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
print "sqlalchemy version:",sqlalchemy.__version__
engine = create_engine('sqlite:///:memory:', echo=False)
metadata = MetaData()
users_table = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String),
)
metadata.create_all(engine)
class User(declarative_base()):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
def __init__(self, name):
self.name = name
Session = sessionmaker(bind=engine)
session = Session()
user1 = User("anurag")
session.add(user1)
session.commit()
# uncommenting next line throws exception 'TypeError: 'User' object is not iterable'
#print dict(user1)
# this one also throws 'TypeError: 'User' object is not iterable'
for u in session.query(User).all():
print dict(u)
Uruchomienie tego kodu na wyjściach systemu:
sqlalchemy version: 0.5.6
Traceback (most recent call last):
File "untitled-1.py", line 37, in <module>
print dict(u)
TypeError: 'User' object is not iterable
python
sqlalchemy
Anurag Uniyal
źródło
źródło
sqlalchemy.util.KeyedTuple
co rząd obiekt z tytułu Pytanie za. Jednak zapytanie w pytaniu używa klasy model (mapowanej), dlatego typem obiektu wiersza jest klasa modelu zamiastsqlalchemy.util.KeyedTuple
.Odpowiedzi:
Możesz uzyskać dostęp do wnętrza
__dict__
obiektu SQLAlchemy, na przykład:źródło
dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
__dict__
zawiera_sa_instance_state
wpis, który należy następnie usunąć. jeśli uaktualnisz do przyszłej wersji i zostaną dodane inne atrybuty, być może będziesz musiał wrócić i ręcznie sobie z nimi poradzić. jeśli chcesz tylko kolumny danych (na przykład, aby pobrać listę wystąpień z zapytania i upuścić je w ramce danych pandy), wówczas{col.name: getattr(self, col.name) for col in self.__table__.columns}
odpowiedź Anurag Uniyal (z ważnymi poprawkami z komentarzy do tej odpowiedzi) wydaje się bardziej zwięzła i zawiera błędy dowód.dict(u)
i poprawnie stwierdza, że rzucaTypeError
.Nie mogłem uzyskać dobrej odpowiedzi, więc używam tego:
Edycja: jeśli powyższa funkcja jest zbyt długa i nie nadaje się do niektórych smaków, to jest to jedna linijka (python 2.7+)
źródło
return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
.row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
aby był to jeden linijka, ale wolę, aby mój kod był czytelny, poziomo krótki, pionowo długix = Column('y', Integer, primary_key=True)
? Żadne z tych rozwiązań nie działa w tym przypadku.return {c.name: getattr(self, c.name) for c in self.__table__.columns}
Jak na @zzzeek w komentarzach:
źródło
query(MyModel).all()
: Obiekt MyModel nie jest iterowalny.W SQLAlchemy v0.8 i nowszych użyj systemu inspekcji .
Zauważ, że
.key
jest to nazwa atrybutu, która może różnić się od nazwy kolumny, np. W następującym przypadku:Ta metoda działa również w przypadku
column_property
.źródło
sqlalchemy.inspect(obj).unloaded
wiersze mają
_asdict()
funkcję, która daje dyktandoźródło
jak wspomniał @balki:
_asdict()
Metoda może być stosowana, jeśli jesteś zapytań pole specyficzny, ponieważ jest zwracany jako KeyedTuple .Natomiast jeśli nie określisz kolumny, możesz użyć jednej z innych proponowanych metod - takich jak ta dostarczona przez @charlax. Pamiętaj, że ta metoda jest ważna tylko dla wersji 2.7+.
źródło
.first()
metodę)?Stare pytanie, ale ponieważ jest to pierwszy wynik dla „wiersza sqlalchemy do dyktowania” w Google, zasługuje na lepszą odpowiedź.
Obiekt RowProxy, który zwraca SqlAlchemy, ma metodę items (): http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
Zwraca po prostu listę krotek (klucz, wartość). Aby przekonwertować wiersz na dyktando, można wykonać następujące czynności:
W Pythonie <= 2.6:
W Pythonie> = 2.7:
źródło
list_of_dicts = [dict(row.items()) for row in rows]
table_name_column_name
, jeśli chcesz inne nazwy (np. Po prostucolumn_name
), użyj.label
metody.session.query( MyTable.column_name.label('column_name'), ... )
Zakładając, że następujące funkcje zostaną dodane do
class User
następujących, zwrócą wszystkie pary klucz-wartość wszystkich kolumn:w przeciwieństwie do innych odpowiedzi zwracane są tylko te atrybuty obiektu, które są
Column
atrybutami na poziomie klasy obiektu. Dlatego nie są uwzględniane_sa_instance_state
żadne inne atrybuty SQLalchemy ani dodane do obiektu. OdniesienieEDYCJA: Zapomnij powiedzieć, że działa to również na odziedziczone kolumny.
hybrid_propery
rozszerzenieJeśli chcesz również dołączyć
hybrid_property
atrybuty, następujące działania będą działać:Zakładam tutaj, że zaznaczasz Kolumny początkiem,
_
aby wskazać, że chcesz je ukryć, albo dlatego, że uzyskujesz dostęp do atrybutu przez,hybrid_property
albo po prostu nie chcesz ich pokazywać. OdniesienieTipp
all_orm_descriptors
zwraca także hybrid_method i AssociationProxy jeśli chcesz je również dołączyć.Uwagi do innych odpowiedzi
Każda odpowiedź (jak 1 , 2 ), która na podstawie
__dict__
atrybutu zwraca po prostu wszystkie atrybuty obiektu. Może to być znacznie więcej atrybutów, niż chcesz. To smutne, że to obejmuje_sa_instance_state
lub dowolny inny atrybut zdefiniowany w tym obiekcie.Każda odpowiedź (np. 1 , 2 ), która jest oparta na
dict()
funkcji, działa tylko na obiektach wierszy SQLalchemy zwracanych przezsession.execute()
nie na klasach, z którymi zdefiniujesz pracę, takich jakclass User
z pytania.Odpowiedź rozwiązywanie który oparty jest na
row.__table__.columns
pewno nie praca.row.__table__.columns
zawiera nazwy kolumn bazy danych SQL. Mogą być one równe tylko nazwie atrybutu obiektu python. Jeśli nie, dostanieszAttributeError
. Odpowiedzi (jak 1 , 2 ) oparte naclass_mapper(obj.__class__).mapped_table.c
nim są takie same.źródło
źródło
Po odpowiedzi @balki, od SQLAlchemy 0.8 możesz użyć _asdict (), dostępnej dla obiektów KeyedTuple. To daje dość prostą odpowiedź na pierwotne pytanie. Po prostu zmień w swoim przykładzie dwie ostatnie linie (pętlę for) dla tego:
Działa to, ponieważ w powyższym kodzie u jest obiektem klasy typu KeyedTuple , ponieważ .all () zwraca listę KeyedTuple. Dlatego ma metodę _asdict () , która ładnie zwraca u jako słownik.
WRT odpowiedź @STB: AFAIK, po czym zwraca .all () jest listą KeypedTuple. Dlatego powyższe działa albo, jeśli podasz kolumnę, albo nie, o ile masz do czynienia z wynikiem .all () zastosowanym do obiektu zapytania.
źródło
.all()
zwraca listęUser
instancji, więc to nie działa.User
instancje nie mają_asdict
metody. Zobacz gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8dWyrażenie, przez które się iteruje, przekształca się w listę obiektów modelu , a nie wiersze. Więc następujące jest ich prawidłowe użycie:
Czy naprawdę musisz przekonwertować je na dyktanda? Jasne, istnieje wiele sposobów, ale wtedy nie potrzebujesz części ORM SQLAlchemy:
Aktualizacja : spójrz na
sqlalchemy.orm.attributes
moduł. Posiada zestaw funkcji do pracy ze stanem obiektu, który może być szczególnie przydatnyinstance_dict()
.źródło
Zapoznaj się z odpowiedzią Alexa Brasetvika , aby rozwiązać problem, możesz użyć jednego wiersza kodu
W sekcji komentarza w odpowiedzi Alexa Brasetvika zzzeek, twórca SQLAlchemy, stwierdził, że jest to „poprawna metoda” problemu.
źródło
resultproxy
?Możesz spróbować to zrobić w ten sposób.
Używa wbudowanej metody w obiekcie zapytania, która zwraca obiekt dictonary obiektu zapytania.
referencje: https://docs.sqlalchemy.org/en/latest/orm/query.html
źródło
_asdict()
metoda, która zasadniczo zamyka nazwy pól wartościami pól i zwraca wynik jako słownik.u
w moim przypadku jest to ciąg znaków i pojawia się błąd `` Model '' obiekt nie ma atrybutu '_asdict' '@hllau poniżej pracował dla mnieZnalazłem ten post, ponieważ szukałem sposobu na konwersję wiersza SQLAlchemy na dyktando. Używam SqlSoup ... ale odpowiedź została zbudowana przeze mnie, więc jeśli to mogłoby pomóc komuś, oto moje dwa centy:
źródło
RowProxy
(c
w tej odpowiedzi) przestrzega protokołu mapowania, więc możesz po prostu zadzwonićdict(c)
.Możesz przekonwertować obiekt sqlalchemy na słownik w ten sposób i zwrócić go jako json / dictionary.
Funkcje pomocnicze:
Funkcja kierowcy:
źródło
Dwie drogi:
1.
2)
źródło
Dokumenty oferują bardzo proste rozwiązanie:
ResultRow._asdict()
źródło
Oto, jak robi to Elixir. Wartość tego rozwiązania polega na tym, że pozwala on rekurencyjnie uwzględniać słownikową reprezentację relacji.
źródło
Za pomocą tego kodu możesz również dodać do zapytania „filtr” lub „dołącz” i to działa!
źródło
To powinno działać.
źródło
Mam odmianę odpowiedzi Marco Mariani, wyrażoną jako dekorator. Główną różnicą jest to, że obsługuje listy jednostek, a także bezpiecznie ignoruje niektóre inne typy zwracanych wartości (co jest bardzo przydatne podczas pisania testów przy użyciu próbnych):
źródło
Aby wypełnić odpowiedź @Anurag Uniyal, oto metoda, która będzie rekurencyjnie śledzić relacje:
źródło
d[relationship.key] = to_dict(val,with_relationships) if val else None
W Pythonie 3.8+ możemy to zrobić za pomocą klasy danych i
asdict
dołączonej do niej metody:Kluczem jest użycie
@dataclass
dekoratora i opatrzenie adnotacjami każdej kolumny swoim typem (: str
częśćname: str = Column(String)
linii).Pamiętaj też, że ponieważ
email
nie jest to adnotacja, nie jest uwzględnione wquery_result_dict
.źródło
Jestem świeżo upieczonym programistą Python i miałem problemy z dostępem do JSON z dołączonymi tabelami. Korzystając z informacji zawartych w odpowiedziach tutaj, zbudowałem funkcję zwracającą rozsądne wyniki do JSON-a, gdzie zawarte są nazwy tabel, unikając konieczności aliasu lub kolizji pól.
Po prostu przekaż wynik zapytania o sesję:
test = Session (). query (VMInfo, Customer) .join (Customer) .order_by (VMInfo.vm_name) .limit (50) .offset (10)
json = sqlAl2json (test)
źródło
jeśli kolumna tabeli modeli nie jest równa kolumnie mysql.
Jak na przykład :
Potrzebuję użyć:
jeśli użyjesz tej metody, możesz uzyskać czas modyfikacji i czas utworzenia, oba są Brak
Ponieważ nazwa atrybutów klasy nie jest równa nazwie magazynu kolumn w mysql
źródło
Zwróć zawartość tego: class:
.KeyedTuple
jako słownikaźródło
Ze względu na wszystkich i siebie, oto jak go używam:
źródło
Ta funkcja może pomóc. Nie mogę znaleźć lepszego rozwiązania problemu, gdy nazwa atrybutu jest inna niż nazwa kolumny.
źródło
Będziesz go potrzebować wszędzie w swoim projekcie, apriciate @anurag odpowiedział, że działa dobrze. do tego momentu używałem go, ale to zepsuje cały twój kod, a także nie będzie działać ze zmianą encji.
Zamiast tego spróbuj odziedziczyć podstawową klasę zapytania w SQLAlchemy
po tym, gdziekolwiek zdefiniujesz swój obiekt, pojawi się metoda „as_dict”.
źródło
W większości scenariuszy nazwa kolumny jest dla nich odpowiednia. Ale może piszesz kod w następujący sposób:
nazwa.kolumny „email_użytkownika”, podczas gdy nazwa pola to „e-mail”, nazwa.kolumny nie mogła działać tak dobrze jak wcześniej.
sqlalchemy_base_model.py
też piszę odpowiedź tutaj
źródło