Я изучаю GraphQL, создавая простое приложение на Python, в основном запускает сканирование nmap, сохраняет вывод в базу данных и может быть запрошен GraphQL API. Кажется, я немного запутался в том, как работает GraphQL.
У меня есть несколько таблиц, которые являются отношениями один-ко-многим: user has many scans, scans have results, results have hosts, hosts have ports, hosts have os. Что я определил с помощью sqlalchemy и использовал graphene
Теперь в моей схеме GraphQL у меня есть:
class Scans(SQLAlchemyObjectType):
class Meta:
model = ScansModel
class ScanResult(SQLAlchemyObjectType):
class Meta:
model = ScanResultModel
class Hosts(SQLAlchemyObjectType):
class Meta:
model = HostInfoModel
class Ports(SQLAlchemyObjectType):
class Meta:
model = PortInfoModel
class Os(SQLAlchemyObjectType):
class Meta:
model = OsInfoModel
class Query(graphene.ObjectType):
user = graphene.Field(User)
scans = graphene.List(Scans)
scan_results = graphene.List(ScanResult)
hosts = graphene.List(Hosts)
ports = graphene.List(Ports)
os = graphene.Field(Os)
def resolve_scans(self, info):
query = Scans.get_query(info)
return query
Теперь, когда я делаю запрос GraphQL, я могу запрашивать сканирование, результаты, информацию о хосте, портинфо, osinfo, без необходимости иметь преобразователи для этих полей. У меня создалось впечатление, что для каждого из этих полей потребуется преобразователь.
Кроме того, мне кажется, что я могу выполнять циклические запросы (так что из scanresults я могу запросить scans, а из scans я могу запросить user) из-за внешних ключей и таблицы отношений.
Это правильное поведение, или я неправильно понимаю, как работает GraphQL?


Я знаю, что преобразователи для каждого поля с SQLAlchemyObjecType обрабатываются внутри библиотеки.
когда я использую mongoengine без использования MongoengineObjectType, я кодирую вот так.
class Query(graphene.ObjectType):
department = graphene.List(of_type=DepartmentField,
name=graphene.String(default_value = "all"))
role = graphene.List(of_type=RoleField,
name=graphene.String(default_value = "all"))
employee = graphene.List(of_type=EmployeeField,
name=graphene.String(default_value = "all"))
def resolve_department(self, info, name):
if name == "all":
department = [construct(DepartmentField, object) for object in DepartmentModel.objects]
return department
else:
department = DepartmentModel.objects.get(name=name)
return [construct(DepartmentField, department)]
def resolve_role(self, info, name):
.
.
.
Что вам нужно сделать:
class ScanResult(SQLAlchemyObjectType):
class Meta:
model = ScanResultModel
scans = graphene.List(Scans, description = "Scans from results.")
def resolve_scans(self, info):
query = Scans.get_query(info)
return query.filter(ScansModel.my_id == self.scans_id).all()
Это, вероятно, позволит вам создавать такие запросы, как:
{
scanresult{
edges {
node {
id
scans{
id
}
}
}
}