Jaki jest najlepszy sposób korzystania z GraphQL z Django podczas korzystania z zewnętrznej bazy danych do pobierania danych z wielu tabel (np. Tworzenie modelu Django w celu reprezentowania danych nie odpowiada pojedyncza tabela w mojej bazie danych)?GraphQL + Django: rozwiązywanie zapytań przy użyciu surowego zapytania PostgreSQL
Moje podejście polegało na tymczasowym zaniechaniu używania modeli Django, ponieważ nie sądzę, abym jeszcze je w pełni rozumiał. (Jestem całkowicie nowy w Django oraz GraphQL.) Przygotowałem prosty projekt z aplikacją z podłączonym zewnętrznym DB PostgreSQL. Podążyłem za wszystkimi ustawieniami z Graphene Django tutorial, a następnie uderzyłem w blokadę drogi, gdy zdałem sobie sprawę, że stworzony przeze mnie model jest połączeniem kilku stołów.
Mam kwerendę, która odsyła właściwe kolumny odwzorowane na pola w moim modelu, ale nie wiem jak zrobić to dynamiczne połączenie tak, że po moim API jest trafiony, zapytuje mojej bazy danych i mapuje wiersze do schematu modelu zdefiniowanego w Django.
Moje podejście od tego czasu polegało na unikaniu modeli i stosowaniu prostszej metody pokazanej w przemówieniu Stevena Luschera: Zero to GraphQL in 30 Minutes.
TLDR;
Celem jest umożliwienie trafienia w mój punkt końcowy GraphQL, skorzystanie z obiektu kursora z mojego django.db.connection, aby uzyskać listę słowników, które powinny zostać przetłumaczone na GraphQLList typu OrderItemTypes (patrz poniżej).
Problemem jest to, że otrzymuję wartości null dla każdej wartości, kiedy uderzył w następujący końcowy z zapytaniem:
localhost:8000/api?query={orderItems{date,uuid,orderId}}
Powroty:
{ "data":{ "orderItems":[ {"date":null, "uuid":null, "orderId":null }, ... ] } }
projektu/main/app /schema.py
import graphene
from django.db import connection
class OrderItemType(graphene.ObjectType):
date = graphene.core.types.custom_scalars.DateTime()
order_id = graphene.ID()
uuid = graphene.String()
class QueryType(graphene.ObjectType):
name = 'Query'
order_items = graphene.List(OrderItemType)
def resolve_order_items(root, args, info):
data = get_order_items()
# data prints out properly in my terminal
print data
# data does not resolve properly
return data
def get_db_dicts(sql, args=None):
cursor = connection.cursor()
cursor.execute(sql, args)
columns = [col[0] for col in cursor.description]
data = [
dict(zip(columns, row))
for row in cursor.fetchall() ]
cursor.close()
return data
def get_order_items():
return get_db_dicts("""
SELECT j.created_dt AS date, j.order_id, j.uuid
FROM job AS j
LIMIT 3;
""")
W moim terminalu drukuję z metody rozstrzygnięcia QueryType i widzę, że dane pomyślnie powracają z mojego połączenia PostgreSQL. Jednak GraphQL daje mi wartości zerowe, więc musi być w metodzie rozwiązania, że niektóre mapowanie jest wkręcane.
[ { 'uuid': u'7584aac3-ab39-4a56-9c78-e3bb1e02dfc1', 'order_id': 25624320, 'date': datetime.datetime(2016, 1, 30, 16, 39, 40, 573400, tzinfo=<UTC>) }, ... ]
Jak poprawnie odwzorować moje dane na pola zdefiniowane w moim ItemItemType?
Oto kilka odnośników:
projekt/main/schematu.py
import graphene
from project.app.schema import QueryType AppQuery
class Query(AppQuery):
pass
schema = graphene.Schema(
query=Query, name='Pathfinder Schema'
)
drzewo plik
|-- project
|-- manage.py
|-- main
|-- app
|-- models.py
|-- schema.py
|-- schema.py
|-- settings.py
|-- urls.py
To było niezwykle pomocne, dziękuję za poświęcenie czasu! Jedna mała edycja to lista wierszy powinna być rozłożona przed przekazaniem do nazwanego 'RowType (* row)'. Ogólnie rzecz biorąc, czy jest to dobra praktyka, czy istnieje lepsze podejście do pobierania danych zewnętrznych? –
Jeśli widzisz moją drugą próbę (inna odpowiedź na to pytanie), użyłem przelicznika dla każdego pola, stosując sugerowane przez ciebie podejście dyktowania [klucz]. Z kilku testów, które właśnie uruchomiłem, wydaje się, że obie metody zwracają dane w tym samym czasie. Zastanawiam się, czy nieco powolny czas powrotu z GraphQL jest normalny (1000 rekordów ~ 3-4 sekundy po buforowaniu, a przed cachine zajmuje to około 6 sekund dla tego samego zestawu danych). –
Jeśli używasz wersji rozwojowej, zapytanie zostanie rozwiązane co najmniej 10 razy szybciej (300 ms?). Można go zainstalować za pomocą 'pip install grafhene-django> = 1.0.dev'. Mam nadzieję, że to pomoże! –