flavors / django-graphql-geojson

GeoJSON support for Graphene Django
https://pypi.python.org/pypi/django-graphql-geojson
MIT License
64 stars 4 forks source link

What if a model has more geodjango fields? #3

Open zmasek opened 6 years ago

zmasek commented 6 years ago

Currently I see only support for one field per model. Is it possible to have more?

Thanks

mongkok commented 6 years ago

Hi @zmasek, right now only one geometry field is allowed within geojson_field.

We could include the GeometryCollection type for a geometry field list, http://geojson.org/geojson-spec.html#geometry-collection

class PlaceType(graphql_geojson.GeoJSONType):

    class Meta:
        model = models.Place
        geojson_field = ('field_a', 'field_b')
{
   "type": "GeometryCollection",
   "geometries": [
      {
         "type": "Point",
         "coordinates": [0, 1]
      },
      {
         "type": "LineString",
         "coordinates": [ [0, 1], [1, 0] ]
      }
   ]
}

what do you think?

zmasek commented 6 years ago

Hi, @mongkok,

I tried to loop through the fields, but had some issues and got impatient. I ended up annotating fields with AsGeoJSON function and displaying them separately. I'd have a list of fields, though. Not a collection because it might be easier to mutate... maybe... thoughts?

mongkok commented 6 years ago

Hi @zmasek,

You should not have any problem with mutations using more than one geometry field. For resolvers, I think the GeometryCollection type could be the most appropriate.

mutation CreatePlace($fieldA: Geometry!, $fieldB: Geometry!) {
  createPlace(fieldA: $fieldA, fieldB: $fieldB) {
    place {
      geometries {
        type
        coordinates
      }
      properties {
        ...
      }
    }
  }
}

For now, you could use properties for the second geometry field:

mutation CreatePlace($fieldA: Geometry!, $fieldB: Geometry!) {
  createPlace(fieldA: $fieldA, fieldB: $fieldB) {
    place {
      geometry {
        type
        coordinates
      }
      properties {
        fieldB {
          type
          coordinates
        }
      }
    }
  }
}
zmasek commented 6 years ago

What if you don't want to bundle, to save bandwidth?

On Fri, Jun 22, 2018, 18:10 Dani notifications@github.com wrote:

Hi @zmasek https://github.com/zmasek,

You should not have any problem with mutations using more than one geometry field. For resolvers, I think the GeometryCollection type could be the most appropriate.

mutation CreatePlace($fieldA: Geometry!, $fieldB: Geometry!) { createPlace(fieldA: $fieldA, fieldB: $fieldB) { place { geometries { type coordinates } properties { ... } } } }

For now you can use properties for the second geometry field:

mutation CreatePlace($fieldA: Geometry!, $fieldB: Geometry!) { createPlace(fieldA: $fieldA, fieldB: $fieldB) { place { geometry { type coordinates } properties { fieldB { type coordinates } } } } }

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/flavors/django-graphql-geojson/issues/3#issuecomment-399514087, or mute the thread https://github.com/notifications/unsubscribe-auth/AAs-Kym6kkPo7gBgaG1bgaz82ak5a5Loks5t_SUKgaJpZM4UtJH0 .

mongkok commented 6 years ago

Then you could select a single geometry field within geojson_field.

zmasek commented 6 years ago

And filtering would work in that case, I presume. How can I help?

mongkok commented 6 years ago

I would like to create the GeometryCollection field soon, PRs are also welcome :)

muriloacs commented 3 years ago

You can simply import the graphql_geojson.converter. This worked for me:

Model

from django.contrib.gis.db import models

class Partner(models.Model):
    name = models.CharField(max_length=100, blank=False)
    coverage_area = models.MultiPolygonField()
    address = models.PointField()

Type

from graphene import relay
from graphene_django.types import DjangoObjectType
from graphql_geojson import converter  # noqa

from myapp.partner.models import Partner

class PartnerType(DjangoObjectType):
    class Meta:
        model = Partner
        filter_fields = ['id']
        interfaces = (relay.Node, )

Query

from graphene import ObjectType, relay
from graphene_django.filter import DjangoFilterConnectionField

from .types import PartnerType

class PartnerQuery(ObjectType):
    partner = relay.Node.Field(PartnerType)
    all_partners = DjangoFilterConnectionField(PartnerType)

Even better because the API response body will not change:

Request

query {
  partner (id: "UGFydG5lclR5cGU6MQ==") {
    id
    name
    coverageArea {
      type
      coordinates
    }
    address {
      type
      coordinates
    }
  }
}

Response

{
  "data": {
    "partner": {
      "id": "UGFydG5lclR5cGU6MQ==",
      "name": "My Partner",
      "coverageArea": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [
                8.988174792345296,
                7.305908202108059
              ],
              [
                9.297306855044836,
                7.673950194244314
              ],
              [
                8.966471297361368,
                7.855224608281604
              ],
              [
                8.906780006290315,
                7.399291991157497
              ],
              [
                8.97732320720076,
                7.316894530231506
              ],
              [
                8.982749040383606,
                7.322387694293275
              ],
              [
                8.988174792345296,
                7.305908202108059
              ]
            ]
          ]
        ]
      },
      "address": {
        "type": "Point",
        "coordinates": [
          6.740986207824642,
          6.225814818469395
        ]
      }
    }
  }
}