Hi,
I have following models:
class Place(models.Model):
categories = models.ManyToManyField(PlaceCategory, related_name='places')
class PlaceCategory(models.Model):
name = models.CharField(max_length=255, unique=True)
md5-31ca6232148ba1c5e2c3900b52753dda
class PlaceNode(DjangoObjectType):
class Meta:
model = Place
interfaces = (graphene.relay.Node, )
md5-8221ac3fcb3f6d4fc8ecaa8cf579d623
class PlaceCategoryNode(DjangoObjectType):
class Meta:
model = PlaceCategory
interfaces = (graphene.relay.Node, )
md5-cf3404bb4bb134b2a688b0ef8520cbad
{
placeCategories {
edges {
node {
id
places {
edges {
node {
id
}
}
}
}
}
}
}
md5-b47e61a8cae941ea66f9cb2048593fca
{
places {
edges {
node {
id
categories {
edges {
node {
id
}
}
}
}
}
}
}
I get errors:
Cannot combine queries on two different base models.
It seems that M2M connection is working improperly and it is unable to fetch related objects from instance where M2M is defined.
Has anyone run into the same problem ?
Issue seems to be related to: https://github.com/graphql-python/graphene/issues/466
Do you have any ideas for a work around? I have just run into this issue.
You can just define custom resolver and return queryset. It should work.
In my case it would be:
class PlaceNode(DjangoObjectType):
class Meta:
model = Place
interfaces = (graphene.relay.Node, )
categories = DjangoFilterConnectionField(PlaceCategoryNode)
def resolve_categories(self, *args):
return self.categories.all()
But this is only a workaround. In my case when I have lots of M2M it is annoying that I have to define custom resolvers for all of them.
It looks that exception is raised by:
DjangoConnectionField.merge_querysets
Method gets two queryset, default_queryset and queryset. Although queryset contains proper instances from m2m connection, default_queryset contains all objects from base model. In my case queryset has PlaceCategory instances while default_queryset has Place instances. That's why it raises error.
Looks to me that DjangoFilterConnectionField.connection_resolver receives wrong default_manager parameter.
Can anyone confirm this ?
I believe I have solved this bug in #181. Feel free to try that out and let me know if it works for you.
@spockNinja is this already in 1.3 release, how can I try it?
@keremgocen No, this was not merged in time for the 1.3 release. There has not been a new release to pypi since this was merged. From the commit log, it looks like a release is pushed about every month or so, so I don't expect it will be too long.
In the meantime, you can pull down master instead of 1.3.
pip uninstall graphene-django
pip install git+https://github.com/graphql-python/graphene-django.git
or in requirements.txt
pip install git+ssh://[email protected]/graphql-python/graphene-django.git#egg=graphene-django
Updated, see bottom for working installation with M2M relation
Passing by. #181 is still not available at the time of this posting.
The requirements.txt version spockNinja provided didn't work for me. The following did instead (deprecated. see updated answer below):
// requirements.txt
...
graphene==1.4.1
git+git://github.com/graphql-python/graphene-django.git#egg=graphene-django
graphql-core==1.1
...
Also remember to do pip uninstall graphene-django and pip install -r requirements.txt before and after making the change respectively. M2M FTW!
Update: A recent merge of the PR #229 on 28 Aug 2017 breaks the ability to pip install from the master branch with the following error:
Collecting graphene-django from git+git://github.com/graphql-python/graphene-django.git@master#egg=graphene-django (from -r requirements.txt (line 43))
Cloning git://github.com/graphql-python/graphene-django.git (to master) to /private/var/folders/89/rncftgg148s_bf25n4kr806c0000gn/T/pip-build-gtuljhuf/graphene-django
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/setuptools/dist.py", line 490, in fetch_build_egg
cmd = self._egg_fetcher
AttributeError: 'Distribution' object has no attribute '_egg_fetcher'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/89/rncftgg148s_bf25n4kr806c0000gn/T/pip-build-gtuljhuf/graphene-django/setup.py", line 77, in <module>
platforms='any',
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/distutils/core.py", line 108, in setup
_setup_distribution = dist = klass(attrs)
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/setuptools/dist.py", line 325, in __init__
self.fetch_build_eggs(attrs['setup_requires'])
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/setuptools/dist.py", line 446, in fetch_build_eggs
replace_conflicting=True,
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/pkg_resources/__init__.py", line 855, in resolve
dist = best[req.key] = env.best_match(req, ws, installer)
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1127, in best_match
return self.obtain(req, installer)
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1139, in obtain
return installer(requirement)
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/setuptools/dist.py", line 495, in fetch_build_egg
dist.parse_config_files()
File "/Users/x/Sites/x.com-v2/src/server/env/lib/python3.6/site-packages/setuptools/dist.py", line 425, in parse_config_files
_Distribution.parse_config_files(self, filenames=filenames)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/distutils/dist.py", line 395, in parse_config_files
parser.read(filename)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/configparser.py", line 697, in read
self._read(fp, filename)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/configparser.py", line 1066, in _read
lineno)
configparser.DuplicateSectionError: While reading from 'setup.cfg' [line 17]: section 'bdist_wheel' already exists
To resolve this for now, pip install the commit before it:
// requirements.txt
...
graphene==1.4.1
git+git://github.com/graphql-python/graphene-django.git@bf2b5a940e8a2c4324fa5550cfd2d61570650e22#egg=graphene-django
graphql-core==1.1
...
Feature to query m2m relation has been built and merged into master via #181, but has not been published to the pypi package. We could use the feature by pulling from master as @spockNinja suggested in the comment above as a workaround until the package is ready. However, recent changes in the graphene-django repository breaks the ability to query m2m relations by pulling from master, so we're reverting to a specific commit right before the breaking change in order to query m2m relations, until the official pypi package with the m2m feature is released.
Most helpful comment
You can just define custom resolver and return queryset. It should work.
In my case it would be:
But this is only a workaround. In my case when I have lots of M2M it is annoying that I have to define custom resolvers for all of them.