当我们执行中继查询时,如何接收存储在数据库中的本地模型 ID(例如 django 模型 ID)?中继定义它自己的 ID 的主要问题所以我不确定我们如何正确处理它。
例如。
query {
allFuelTypes (codeMatch: "g") {
edges {
node {
id,
code,
label
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
将打印
{
"data": {
"allFuelTypes": {
"edges": [
{
"node": {
"id": "RnVlbFR5cGVOb2RlOjM=",
"code": "g",
"label": "Gas"
}
}
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中id是石墨烯中继 ID,但我想查看模型 ID。
我看到的唯一一种可能的方法是在石墨烯模式中为模型 ID 字段创建一些别名,并从 Django 模型中手动获取此 ID。但也许存在一些更动态的方式来实现相同的结果?
谢谢你的帮助!
PS查询的实现并不重要。这只是一个虚拟演示
我使用 Django 和 Graphene 在 Python 中实现了 GraphQL 服务器。我有使用模型形式的突变,大致如下所示:
def mutate(self, info, **kwargs):
form = MyModelForm(kwargs)
if form.is_valid():
form.save()
return MyMutation(instance=form.instance)
raise GraphQLError(json.dumps(form.errors))
Run Code Online (Sandbox Code Playgroud)
也就是说,如果表单验证失败,则将表单错误作为 JSON 字符串发送,以便前端可以整齐地解包错误。这一切都很好。
但是,如果存在其他错误 - 比如说数据库存在问题,当表单尝试保存时会引发异常,或者存在拼写错误,那么石墨烯的默认行为是获取错误消息并在 GraphQL 中传输它错误列表给客户端。这意味着检查响应的任何人都可以看到来自服务器的原始错误消息。这似乎不明智 - 如果该错误消息包含我不想泄漏的信息怎么办?显然,解决方案是创建一个不抛出异常的应用程序,但我无法预见一切。有没有办法告诉石墨烯更加离散,并在错误不是由我显式引发 GraphQLError 引起时提供通用错误消息,而不是仅仅将所有内容发送到客户端?
当前正在发生的事情的一个例子:
{"errors":[{"message":"name 'LogiForm' is not defined","locations":[{"line":2,"column":3}],"path":["login"]}],"data":{"login":null}}
Run Code Online (Sandbox Code Playgroud)
这个特定的示例不是安全问题,很容易在生产之前捕获,但这只是一个示例 - 即使不是安全威胁,我的服务器让客户端可以查看其内部错误消息似乎有点不专业。
我目前正在用装饰器解决这个问题:
def hide_error(mutate):
def new_func(*args, **kwargs):
try:
return mutate(*args, **kwargs)
except Exception as e:
raise e if isinstance(e, GraphQLError) else Exception("Error.")
return new_func
Run Code Online (Sandbox Code Playgroud)
但还有更好的办法吗?您“应该”有办法解决这个问题吗?
python error-handling graphql graphene-python graphene-django
目前我正在从文档页面运行 django-graphqljwt 的基本示例。https://django-graphql-jwt.domake.io/en/latest/quickstart.html
import graphene
import graphql_jwt
class Mutation(graphene.ObjectType):
token_auth = graphql_jwt.ObtainJSONWebToken.Field()
verify_token = graphql_jwt.Verify.Field()
refresh_token = graphql_jwt.Refresh.Field()
schema = graphene.Schema(mutation=Mutation)
Run Code Online (Sandbox Code Playgroud)
但是,如果我运行tokenAuth突变,它会在GraphiQL界面中抛出以下错误。请注意,如果我输入不正确的凭据,它会抛出一个“ Please enter valid credentials”而不是下面的。
{
"errors": [
{
"message": "'str' object has no attribute 'decode'",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"tokenAuth"
]
}
],
"data": {
"tokenAuth": null
}
}
Run Code Online (Sandbox Code Playgroud) 我想创建两个现有类型(FirstType 和 SecondType)的 UnionType(graphene.Union) 并且能够解决这个联合类型的查询。
class FirstType(DjangoObjectType):
class Meta:
model = FirstModel
class SecondType(DjangoObjectType):
class Meta:
model = SecondModel
class UnionType(graphene.Union):
class Meta:
types = (FirstType, SecondType)
Run Code Online (Sandbox Code Playgroud)
因此,使用此模式,我想在某些列表 [pks] 中使用 pk 查询 FirstType 和 SecondType 中的所有对象
query {
all_items(pks: [1,2,5,7]){
... on FirstType{
pk,
color,
}
... on SecondType{
pk,
size,
}
}
}
Run Code Online (Sandbox Code Playgroud)
FirstType 的 PK 通常不在 SecondType 中。
我试过如下
def resolve_items(root, info, ids):
queryset1 = FirstModel.objects.filter(id__in=pks)
queryset2 = SecondModel.objects.filter(id__in=pks)
return queryset1 | queryset2
Run Code Online (Sandbox Code Playgroud)
但它给出了一个错误:“无法在两个不同的基本模型上组合查询。”
我希望查询得到以下响应:
{ 'data': …Run Code Online (Sandbox Code Playgroud) 我看过很多关于如何在石墨烯中实现许可系统的讨论,但除了这些讨论之外,还没有看到任何明确的实际成果。关于该主题的一些讨论示例如下:
不幸的是,这些都没有推荐在石墨烯中实现权限的首选方法。有谁知道目前执行此操作的最佳实践是什么?
如果这个问题在其他地方得到回答,那么我很抱歉,但是下班后两天,仍然没有雪茄......
我有一个播放器模型:
class Player(models.Model):
name = models.CharField(max_length=60)
discord_id = models.CharField(max_length=60, null=True)
known_npcs = models.ManyToManyField(NPC)
Run Code Online (Sandbox Code Playgroud)
玩家可以认识很多NPC,而任何NPC都可以被很多玩家认识。
NPC没什么特别的:
class NPC(models.Model):
image = models.ImageField()
name = models.CharField(max_length=50)
description = models.TextField()
Run Code Online (Sandbox Code Playgroud)
谜题的最后一部分是事实,事实是附加到 NPC 的一些信息,但是一个人可以认识一个 NPC,但玩家不一定知道所有与 NPC 相关的事实,因此事实看起来像这样:
class Fact(models.Model):
fact = models.TextField()
known_by = models.ManyToManyField(Player)
npc = models.ForeignKey(NPC, on_delete=models.DO_NOTHING, null=True)
Run Code Online (Sandbox Code Playgroud)
现在在石墨烯中,我想创建一个 Player 和 allPlayers 查询,它会给我这个:
{
allPlayers {
name
knownNPCs {
image
name
description
factsKnown {
fact
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中已知的事实只是基于 Fact 对象中的多对多关系的事实。
到目前为止,我创建的内容会返回数据,但不会根据玩家父级过滤事实,只是显示与 npc 相关的所有事实:(
事实图式
class FactType(DjangoObjectType):
class Meta:
model = …Run Code Online (Sandbox Code Playgroud) 首先,谢谢!已经 1 年没有问问题了,因为我总能找到答案。你是一个巨大的帮助。
今天,我确实有一个我自己无法解决的问题。拜托了,我希望你能在这件事上帮助我。
上下文:我在一个使用 Django 框架的项目上工作,我有一些用 react.js 制作的动态页面。我在两者之间使用的 API 是基于 graphQL 的。Apollo 为客户端,graphene-django 为后端。
我想做一个由 GraphQL 查询制成的动态页面,该查询具有一组(DjangoObjectType 类中的声明字段,由 Django 查询制成),并且我希望能够使用参数 A 动态过滤父级,并使用参数 B。我的问题是如何找到一种方法将参数 B 传递给集合以对其进行过滤。
我将基于 graphQL 文档实现的 graphQL
query DistributionHisto
(
$id:ID,
$limit:Int
)
{
distributionHisto(id:$id)
{
id,
historical(limit:$limit)
{
id,
date,
histo
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我不明白如何在后端将 (limit:$limit) 传递给我的集合。
这是我的 schema.py
import graphene
from graphene_django.types import DjangoObjectType
class DistributionType(DjangoObjectType):
class Meta:
model = DistributionTuple
historical = graphene.List(HistoricalTimeSeriesType)
def resolve_historical(self, info):
return HistoricalTimeSeries.objects.filter(
distribution_tuple_id=self.id
).order_by('date')[:2]
class Query(object):
distribution_histo …Run Code Online (Sandbox Code Playgroud) 我已阅读有关如何在这些链接中排除(隐藏)django 和 graphene_django 中的某些字段的信息:
想象一下,我们有以下Post模型,它具有模型的外键User。
应用程序/帖子/models.py
from django.db import models
from apps.users.models import User
class Post(models.Model):
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
null=False
)
created_at = models.DateTimeField(
auto_now_add=True,
)
title = models.TextField(
null=False,
max_length=100,
)
content = models.TextField(
null=False,
)
def __str__(self):
return self.title
Run Code Online (Sandbox Code Playgroud)
应用程序/用户/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser, models.Model):
phone_no = models.CharField(
blank=True,
null=True,
default="",
max_length=10,
verbose_name="Phone Number",
)
avatar = models.ImageField(
null=True,
upload_to='static', …Run Code Online (Sandbox Code Playgroud) 说我有,
class PersonNode(DjangoObjectType):
class Meta:
model = Person
fields = ('first_name', 'last_name', 'age',
'sex', 'alive', 'unique_identifier',)
filter_fields = ('first_name', 'last_name', 'age',
'sex', 'alive', 'unique_identifier',)
interfaces = (graphene.relay.Node,)
class PersonNodeInput(graphene.InputObjectType):
first_name = graphene.String()
last_name = graphene.String()
# rest of person model fields
class Valid(graphene.ObjectType):
ok = graphene.Boolean()
class Query(graphene.ObjectType):
validate_person = graphene.Field(Valid, args={
"data": PersonNodeInput()})
person = graphene.relay.Node.Field(PersonNode)
all_people = DjangoFilterConnectionField(PersonNode)
def resolve_validate_person(root, info, data):
print("resolve validate person")
return Valid(ok=True)
Run Code Online (Sandbox Code Playgroud)
是否可以避免写出PersonNodeInput?如果您可以对“DjangoInputObjectType”之类的内容进行子类化并在 Meta 属性中指定所需的模型和字段,那就太好了。
我正在用 Python、GraphQL (graphene-django) 和 Django 构建一个简单的 CRUD 接口。Ingredient包含与另一个对象 ( Category) 的外键关系的对象 ( )的 CREATE 突变将不起作用。我想为 GraphQL 提供 CategoryObject 的 id 而不是整个类别实例。然后在后端它应该绘制与 Category 对象的关系。
在 Django 模型中,成分对象包含外键类别对象的一个实例(参见下面的代码)。这里是否需要整个类别对象来绘制关系并使用Ingredient.objects.select_related('category').all()?
create 突变期望IngredientInput包括外键关系的所有属性和整数字段。因此,graphQL 突变本身目前可以按照我的意愿工作。
我的问题与这个问题相似,但这些答案对我没有帮助。
模型.py:
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
notes = models.TextField()
class Meta:
verbose_name = u"Category"
verbose_name_plural = u"Categories"
ordering = ("id",)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=100)
notes = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
class Meta:
verbose_name = …Run Code Online (Sandbox Code Playgroud)