0

In Graphene-Django and GraphQL I am trying to create a resolve_or_create method for nested data creation inside my mutations.

I'm trying to pass a dictionary with the input from the user as a **kwarg to my resolve_or_create function, and though I can see "location" in the variable watcher (in VSCode), I continuously am getting the error 'dict' object has no attribute 'location'

Here's my resolve_or_create method:

def resolve_or_create(*args, **kwargs):
    input = {}
    result = {}
    input.location = kwargs.get('location', None)

    if input.location is not None:
        input.location = Location.objects.filter(pk=input.location.id).first()
        if input.location is None:
            location = Location.objects.create(
                location_city = input.location.location_city,
                location_state = input.location.location_state,
                location_sales_tax_rate = input.location.location_sales_tax_rate
            )
            if location is None:
                return None
        result.location = location
    return result

and my CreateCustomer definition, where this method is being called

class CreateCustomer(graphene.Mutation):
    class Arguments:
        input = CustomerInput(required=True)
    
    ok = graphene.Boolean()
    customer = graphene.Field(CustomerType)

    @staticmethod
    def mutate(root, info, input=None):
        ok = True
        resolved = resolve_or_create(**{'location':input.customer_city})
        customer_instance = Customer(
            customer_name = input.customer_name,
            customer_address = input.customer_address,
            customer_city = resolved.location,
            customer_state = input.customer_state,
            customer_zip = input.customer_zip,
            customer_email = input.customer_email,
            customer_cell_phone = input.customer_cell_phone,
            customer_home_phone = input.customer_home_phone,
            referred_from = input.referred_from
        )
        customer_instance.save()
        return CreateCustomer(ok=ok, customer=customer_instance)

Here is an example mutation that would create a new customer with an existing location

mutation createCustomer {
  createCustomer(input: {
    customerName: "Ricky Bobby",
    customerAddress: "1050 Airport Drive",
    customerCity: {id:1},
    customerState: "TX",
    customerZip: "75222",
    customerEmail: "mem",
    customerCellPhone: "124567894",
    referredFrom: "g"
  }) {
    ok,
    customer{
      id,
      customerName,
      customerAddress,
      customerCity {
        id
      },
      customerState,
      customerZip,
      customerEmail,
      customerCellPhone,
      referredFrom
    }
  }
}

and here is an example mutation that would create a customer with a new location

mutation createCustomer {
  createCustomer(input: {
    customerName: "Ricky Bobby",
    customerAddress: "1050 Airport Drive",
    customerCity: {locationCity: "Dallas", locationState: "TX", locationSalesTaxRate:7.77},
    customerState: "TX",
    customerZip: "75222",
    customerEmail: "mem",
    customerCellPhone: "124567894",
    referredFrom: "g"
  }) {
    ok,
    customer{
      id,
      customerName,
      customerAddress,
      customerCity {
        id
      },
      customerState,
      customerZip,
      customerEmail,
      customerCellPhone,
      referredFrom
    }
  }
}

So my question is two-fold.

First, how can I retrieve my passed in location dict from kwargs?

Second, is there a better way to be resolving and creating nested data than this? Would this be expected behavior in a best-practice GraphQL API?

I have also tried resolve_or_create(location=input.customer_city})

Joe Howard
  • 307
  • 5
  • 27

1 Answers1

0

I realized my syntax for dictionary assignment and access was wrong.

Corrected function:

def resolve_or_create(*args, **kwargs):
    input = {}
    result = {}
    candidate = None
    input['location'] = kwargs['location']
    input['customer'] = kwargs.get('customer', None)
    input['technician'] = kwargs.get('tech', None)

    if input['location'] is not None:
        if 'id' in input['location']:
            candidate = Location.objects.filter(pk=input['location']['id']).first()
            result['location'] = candidate
        if candidate is None:
            result['location'] = Location.objects.create(
                location_city = input['location']['location_city'],
                location_state = input['location']['location_state'],
                location_sales_tax_rate = input['location']['location_sales_tax_rate']
            )
            if result['location'] is None:
                return None
    return result

I would still like to discuss the most effective way to accomplish created and mutating nested data in graphene-django. Is there a DRYer way to achieve what I'm looking to do or something I'm missing?

Joe Howard
  • 307
  • 5
  • 27