![](/img/trans.png)
[英]How to update the model with the foreignkey relation in Graphene-Django Relay?
[英]Django ForeignKey field ignored by graphene-django when "to" value is a string
版本:
Python: 3.8
Django: 3.2.2
graphene-django: 2.15.0
从 3.0 版本升级到 Django 3.2.2 后,观察到以下问题有效。
我在使用带有 ForeignKey 字段的 graphene-django 时遇到问题,它被忽略了,因为to
的值是一个字符串。 忽略,我的意思是它没有转换为 GraphQL 字段。 这是 Django model:
class CableTermination(models.Model):
cable = models.ForeignKey(
to='dcim.Cable',
on_delete=models.SET_NULL,
related_name='+',
blank=True,
null=True
)
to
的值是避免循环导入的字符串。 这也是此 model 上的唯一字段(除了pk
)。
我从这个 class 创建了一个 DjangoObjectType:
class CableTerminationNodeType(DjangoObjectType):
class Meta:
model = CableTermination
我也有一种电缆类型:
class CableNodeType(DjangoObjectType):
class Meta:
model = Cable
但是在启动时我看到这个错误:
env/lib/python3.8/site-packages/graphql/type/definition.py", line 214, in define_field_map
assert isinstance(field_map, Mapping) and len(field_map) > 0, (
AssertionError: CableTerminationNodeType fields must be a mapping (dict / OrderedDict) with field names as keys or a function which returns such a mapping.
我已经将其追踪到长度为 0 的field_map
。我还观察到上述电缆字段的转换器被调用但返回 None。
这是因为field.related_model
返回字符串dcim.Cable
但注册表只能通过 class 查找。 所以最终, _type
在下面是None
:
@convert_django_field.register(models.OneToOneField)
@convert_django_field.register(models.ForeignKey)
def convert_field_to_djangomodel(field, registry=None):
model = field.related_model
def dynamic_type():
_type = registry.get_type_for_model(model)
if not _type:
return
return Field(_type, description=field.help_text, required=not field.null)
return Dynamic(dynamic_type)
有人遇到过类似的问题吗? 或者有什么我应该做的不同的事情吗?
看来我可以通过覆盖转换器并使用django.apps
加载 model 来解决此问题。 所以我想知道这是否是一个有效的错误和修复(我应该为此提出 PR)或者我的结果出了什么问题。
@convert_django_field.register(models.OneToOneField)
@convert_django_field.register(models.ForeignKey)
def convert_field_to_djangomodel(field, registry=None):
model = field.related_model
if isinstance(model, str):
split = model.split('.', 1)
model = apps.get_model(app_label=split[0], model_name=split[1])
def dynamic_type():
_type = registry.get_type_for_model(model)
if not _type:
return
return Field(_type, description=field.help_text, required=not field.null)
return Dynamic(dynamic_type)
似乎这是问题所在,但事实并非如此。
问题是您没有注册电缆类型。 当您查看调试器时,您会看到field.related_model
已经解析: Django 这样做,石墨烯甚至看不到字符串引用。
但是,如果您没有通过为其创建 DjangoObjectType 并将其导入到架构中将 Cable model 导入注册表,那么 graphene_django 将找不到它。
为了清楚起见并假设带有 CableTermination model 的应用程序被称为“main”并且您的设置文件位于project/
中:
# file: dcim/schema.py
from graphene_django import DjangoObjectType
from .models import Cable
class CableType(DjangoObjectType):
class Meta:
model = Cable
# main/schema.py
import graphene
from graphene_django import DjangoObjectType
from .models import CableTermination
class CableTerminationType(DjangoObjectType):
class Meta:
model = CableTermination
class Query(graphene.ObjectType):
terminations = graphene.List(CableTerminationType)
@staticmethod
def resolve_terminations(root, info, **kwargs):
return CableTermination.objects.all()
#project/schema.py:
import graphene
import main.schema
# import the schema with the CableType, so it registers itself
import dcim.schema
class Query(main.schema.Query, graphene.ObjectType):
pass
schema = graphene.Schema(query=Query)
# project/settings.py
GRAPHENE = {
"SCHEMA": 'project.schema.schema'
}
这是最小的设置。 当然,如果您为 Cable model 创建查询和/或突变,这将自行解决,因为您需要为其创建一个类型。
无法使用 Django 3.2.3 重现您所描述的内容。 上述解决方案仍然适用于我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.