Open Gentatsu opened 4 years ago
can you show your type class and resolver?
class Task(Document):
meta = {"collection": "tasks", "strict": False}
dateStarted = DateTimeField(default=datetime.now)
state = StringField()
class CustomNode(Node):
class Meta:
name = 'Node'
@staticmethod
def to_global_id(type, id):
return id
class Task_T(MongoengineObjectType):
class Meta:
model = Task
interfaces = (CustomNode,)
tasks = MongoengineConnectionField(Task_T)
you should either
1) Define get_node_from_global_id
as mentioned here https://docs.graphene-python.org/en/latest/relay/nodes/#custom-nodes
or
2) Implement a resolver for your field on the parent object that takes into account the id filter
Not sure if this belongs in the issues sections of this repo
A custom resolver defeats the purpose of the MongoengineConnectionField
. I like being able to expose the model and filter on any item without explicitly defining them in resolver.
The get_node_from_global_id
was the kicker. It's not very well defined in that example as it forces me to define the type. With a bit of cheeky debugging, I found a way to resolve generic types:
@staticmethod
def get_node_from_global_id(info, global_id, only_type=None):
model = getattr(info.parent_type.graphene_type, info.field_name).model
return model.objects.get(id=global_id)
Hope this helps someone in the future. I think it should be an issue as there are many instances where people want to resolve non-global ids and filter on them.
yeah having a generic get_node_from_global_id
is simple as long as you are doing a plain get, once you get into embedded documents and nesting thats where it becomes harder
I've got both in mine actually! You're very correct! I tried filtering ids on an embedded document w/ a different field name.
I've modified it to this to work generically:
@staticmethod
def get_node_from_global_id(info, global_id, only_type=None):
model = info.return_type.graphene_type.Edge.node.type._meta.model
return model.objects.get(id=global_id)
Tested on embedded field + list of reference fields and seems to work.
how does this work on EmbeddedDocuments when they dont have an objects property?
You're right. This does not work on filtering EmbeddedDocuents. I needed to look at the last several records of an EmbeddedDocument, and it kept complaining about not having a pk
property. I tried adding in a primary key w/ initialisating an ObjectId
, setting primary_key, unique, required
to True
but to no avail.
I've tried it with both EmbeddedListField
and ListField(EmbeddedDocument)
.
Not sure if I should create a separate issue for this?
This is because graphene_mongo expects the pk property to be present on your models (for some reason), if your embedded document has a natural/surrogate key, then you can add an alias called pk
on your EmbeddedDocument subclass for this key as a workaround:
@property
def pk(self):
return self.id
replacing id
with the name of the attr you want to use
Hello, is there any progress or suggestions in how to filter EmbeddedDocuments?
I have been trying for a while now and I've stumbled upon this open issue for the same thing.
I have changed a few lines in the fields.py
file like so:
# This is line 221 in the file
if callable(getattr(self.model, "objects", None)):
iterables = self.get_queryset(self.model, info, **args)
list_length = iterables.count()
else:
iterables = getattr(_root, info.field_name, [])
_args = args.copy()
# I don't know what the "pk__in" argument does so I delete this argument in the copy made so that it doesn't cause conflicts.
del _args["pk__in"]
# I don't know if there is a more efficient way of doing this search
for arg_name, arg in _args.items():
iterables = [_object for _object in iterables if getattr(_object, arg_name, None) == arg]
list_length = len(iterables)
Right now, it works and have not ran into any issues while doing a few tests.
When I try to filter by id using
MongoengineConnectionField
, using this query: