我正在通过构建一个简单的 python 应用程序来学习 GraphQL,基本上运行
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 查询时,我可以查询扫描、结果、主机信息、端口信息、操作系统信息,而无需为这些字段提供解析器。我的印象是每个字段都需要一个解析器。
此外,由于外键和关系表,我似乎能够进行循环查询(因此从
scanresults
我可以查询scans
,从scans
我可以查询user
)。
这是正确的行为,还是误解了 GraphQL 的工作原理?
你需要做的是:
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
}
}
}
}
我知道 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):
.
.
.