Git Product home page Git Product logo

Comments (11)

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024 1

Sounds good and appreciated!

from graphene-gis.

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024 1

Very much appreciated for the assistance! That worked perfectly for storing and processing the data. I'm happy to review the docs when they are updated - just let me know :)

from graphene-gis.

EverWinter23 avatar EverWinter23 commented on June 19, 2024

Hey @OpenDataAlex,

Check this mutation test, I think it will make the picture clearer.

In hindsight, I see how that could've been confusing, we don't need to create a new class just for handling geometries, they are handled implicitly with the model. I'll make changes to the docs, should've added a real world example.

I was able to spot a couple of problems here, I have outlined it below:

class LocationCreateMutation(graphene.Mutation):
    class Arguments:
        drawn_area = graphene.Argument(PolygonScalar)

    location = graphene.Field(LocationType)

    def mutate(self, info, drawn_area):
        drawn_area = PolygonModelType(drawn_area=drawn_area)

        location = Location()
        # PROBLEM: location.drawn_area should be of type PolygonField, we cannot assign it to class
        location.drawn_area = drawn_area 
        location.save()
        return  LocationCreateMutation(location=location)

This is how one should proceed with mutations-- specifically for your use case:

# filename: schema.py
import graphene
from graphene_django import DjangoObjectType
from graphene_gis.converter import gis_converter
from graphene_gis.scalars import PolygonScalar

class LocationType(DjangoObjectType):
    class Meta:
        model = Location
        fields = ("id", "drawn_area")
        interfaces = (graphene.relay.Node, )

class LocationCreateMutation(graphene.Mutation):
    location = graphene.Field(LocationType)
    
    class Arguments:
        drawn_area = graphene.Argument(PolygonScalar)

    def mutate(self, info, drawn_area):
        location = LocationType(drawn_area=drawn_area)
        return LocationCreateMutation(location=location)

I hope that resolves your issue, if not lemme know. :)

PS: We've been using this in production for two years, it's battle tested, and we haven't encountered any problems with it. Async resolvers would be nice though-- which would require upgrading to django3.0 and graphene 3.0.

from graphene-gis.

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024

Makes total sense and thank you for the quick response! I modified my code and it looks like it's good to go. Much appreciated :)

from graphene-gis.

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024

@EverWinter23 One more hopefully quick question. Now that I've got location storing as a LocationType, how do I save it back to the database? I've yet to find an example in my searching.

from graphene-gis.

EverWinter23 avatar EverWinter23 commented on June 19, 2024

Glad that worked, @OpenDataAlex. Checkout this tutorial, it's really good.

This one is nice as well.

Ummm, I think this should do it. I made an error in the earlier version 😅

class LocationCreateMutation(graphene.Mutation):
    id = graphene.ID()
    drawn_area = graphene.Field(graphene.String, to=PolygonScalar())
    
    class Arguments:
        drawn_area = graphene.Argument(PolygonScalar)

    def mutate(self, info, drawn_area):
        location = Location(drawn_area=drawn_area)
        location.save()
        return LocationCreateMutation(
            id=location.id,
            drawn_area=location.drawn_area
       )

From the docs:

#3: The mutation method: it creates a link location in the database using the data sent by the user, through the url and description drawn_area parameter. After, the server returns the CreateLink LocationCreateMutation class with the data just created. See how this matches the parameters set on #1.

from graphene-gis.

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024

@EverWinter23 Unfortunately, when I go back to that I get this error:

"Cannot set Location SpatialProxy (POLYGON) with value of type: <class 'dict'>"

I successfully got back the location object when it was the LocationType.

from graphene-gis.

EverWinter23 avatar EverWinter23 commented on June 19, 2024

@OpenDataAlex I have updated the previous codeblock, and made some corrections. Lemme know if that doesn't work :)

Edit: I generally use serializer for mutations to avoid verbose mutation blocks.

from graphene-gis.

OpenDataAlex avatar OpenDataAlex commented on June 19, 2024

@EverWinter23 I'm getting the same error unfortunately :/ I'm fine using whatever - I'm fairly new to Graphene/GraphQL and still learning :)

from graphene-gis.

EverWinter23 avatar EverWinter23 commented on June 19, 2024

I will setup a demo project which showcases querying and mutations with postgis and push it by tomorrow, that will be more helpful. Difficult to debug on github threads.

from graphene-gis.

EverWinter23 avatar EverWinter23 commented on June 19, 2024

Hi 👋 @OpenDataAlex,

Here is the sample project-- geoql. I am yet to add README.md, I have tested the stuff out, I'll add tests and description over the weekend. The repo also uses postgis db using docker, I am yet to put the django itself inside docker, it will be a good way to showcase the libraries capabilities.

Everything works as expected. The following code is from this project. Setup your mutations as follows, I have also tested them out locally:

# filename: models.py
import uuid
from django.contrib.gis.db import models


class F1Track(models.Model):
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )

    name = models.CharField(max_length=128, null=False)
    length = models.PositiveIntegerField(null=False)
    geometry = models.PolygonField(null=False)
# filename: mutation.py
import graphene

from graphene_gis.scalars import PolygonScalar
from django.contrib.gis.geos import GEOSGeometry

from formula1.models import F1Track


class CreateF1TrackMutationWithWKT(graphene.Mutation):
    id = graphene.ID()
    name = graphene.String()
    length = graphene.Int()
    geometry = PolygonScalar()

    class Arguments:
        name = graphene.String()
        length = graphene.Int()
        geometry = graphene.String()

    def mutate(self, info, name, length, geometry):
        track = F1Track(name=name, length=length, geometry=geometry)
        track.save()

        return CreateF1TrackMutationWithWKT(
            id=track.id,
            name=track.name,
            length=track.length,
            geometry=track.geometry,
        )


class CreateF1TrackMutationWithGeoJSON(graphene.Mutation):
    id = graphene.ID()
    name = graphene.String()
    length = graphene.Int()
    geometry = PolygonScalar()

    class Arguments:
        name = graphene.String()
        length = graphene.Int()
        geometry = graphene.JSONString()

    def mutate(self, info, name, length, geometry):
        track = F1Track(name=name, length=length, geometry=GEOSGeometry(f"{geometry}"))
        track.save()

        return CreateF1TrackMutationWithGeoJSON(
            id=track.id,
            name=track.name,
            length=track.length,
            geometry=track.geometry,
        )

In the graphiql console use the following queries:

mutation TrackMutationWithWKT {
    createTrack(
      name:"Bahrain",
      length:500,
      geometry: "SRID=4326;POLYGON ((-80 25, -65 18, -64 32, -80 25))"
    ) {
      id
      name
      length,
      geometry
    }
  }
  
  mutation TrackMutationWithJSON {
    createTrackWithGeojson(
      name:"Bahrain 2.0",
      length:500,
      geometry: "{\"type\":\"Polygon\",\"coordinates\":[[[-80,25],[-65,18],[-64,32],[-80,25]]]}"
    ) {
      id
      name
      length,
      geometry
    }
  }
  
  query GetTracks{
    allTracks {
      edges {
        node {
          id
          name
          length,
          geometry
        }
      }
    }
  }

from graphene-gis.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.