Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add url field to GraphQL output #4163

Merged
merged 11 commits into from
Aug 22, 2023

Conversation

jamesharr
Copy link
Contributor

Closes: #3913

What's Changed:

  • Creates a new base class for GraphQL objects, that includes a url field and a resolve method

  • Bases GraphQL objects on this new base class so that url field is available in the GraphQL API

  • Explanation of Change(s)

  • Added change log fragment(s) (for more information see the documentation)

  • Attached Screenshots, Payload Example

  • Unit, Integration Tests

  • Documentation Updates (when adding/changing features)

  • Example Plugin Updates (when adding/changing features)

  • Outline Remaining Work, Constraints from Design

@jamesharr jamesharr mentioned this pull request Jul 25, 2023
12 tasks
Copy link
Contributor

@glennmatthews glennmatthews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR - looks like a promising approach!

nautobot/extras/graphql/types.py Outdated Show resolved Hide resolved
nautobot/extras/graphql/types.py Outdated Show resolved Hide resolved
url = graphene.String()

def resolve_url(self, args):
return self.get_absolute_url(api=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably would be good to add some error handling here in case it somehow gets a model class that doesn't implement get_absolute_url(api=True)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this was maybe originally based on next and then moved to develop. We don't have the api kwarg in get_absolute_url on develop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May need to rework this then, as the goal of the issue, AIUI, was to return the REST API URL for the object - the UI URL is less useful in a GraphQL context. Maybe use get_route_for_model in 1.x?

@glennmatthews
Copy link
Contributor

Looks like some tests may need to be updated/modified, also please add a changelog fragment. Thanks!

@gsnider2195 gsnider2195 self-assigned this Aug 20, 2023
@gsnider2195 gsnider2195 marked this pull request as ready for review August 21, 2023 20:00
import graphene_django_optimizer as gql_optimizer


class ContentTypeType(gql_optimizer.OptimizedDjangoObjectType):
class OptimizedNautobotObjectType(gql_optimizer.OptimizedDjangoObjectType):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need some documentation in nautobot/docs/plugins/development.md in the "Creating your own graphql type object" section?

@gsnider2195
Copy link
Contributor

@lampwins should this be rebased to next? Would this be considered a bug fix or a feature?

@gsnider2195
Copy link
Contributor

Sample output from current commit:

{
  locations {
    id,
    name,
    url,
    location_type {
      id,
      url
    }
  }
}
{
  "data": {
    "locations": [
      {
        "id": "48eec2fe-15b9-4dde-8a1e-d9368a68db3b",
        "name": "Campus-00",
        "url": "http://localhost:8080/api/dcim/locations/48eec2fe-15b9-4dde-8a1e-d9368a68db3b/",
        "location_type": {
          "id": "83494c52-116f-47ff-9cfb-c42b7f9dda65",
          "url": "http://localhost:8080/api/dcim/location-types/83494c52-116f-47ff-9cfb-c42b7f9dda65/"
        }
      },
      {
        "id": "b28d3a98-b88f-4923-a2f2-fb6299c99b45",
        "name": "Building-01",
        "url": "http://localhost:8080/api/dcim/locations/b28d3a98-b88f-4923-a2f2-fb6299c99b45/",
        "location_type": {
          "id": "147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7",
          "url": "http://localhost:8080/api/dcim/location-types/147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7/"
        }
      },
      {
        "id": "b47984fc-bba4-4db2-84a5-04cc2a16bba4",
        "name": "Elevator-02",
        "url": "http://localhost:8080/api/dcim/locations/b47984fc-bba4-4db2-84a5-04cc2a16bba4/",
        "location_type": {
          "id": "e792af80-ce55-40b0-a042-966e4bd1e21c",
          "url": "http://localhost:8080/api/dcim/location-types/e792af80-ce55-40b0-a042-966e4bd1e21c/"
        }
      },
      {
        "id": "26194285-4399-4ef1-be85-87538ed30ed6",
        "name": "Elevator-09",
        "url": "http://localhost:8080/api/dcim/locations/26194285-4399-4ef1-be85-87538ed30ed6/",
        "location_type": {
          "id": "e792af80-ce55-40b0-a042-966e4bd1e21c",
          "url": "http://localhost:8080/api/dcim/location-types/e792af80-ce55-40b0-a042-966e4bd1e21c/"
        }
      },
      {
        "id": "dbf08a2f-e486-44ba-b343-c321801cc724",
        "name": "Elevator-16",
        "url": "http://localhost:8080/api/dcim/locations/dbf08a2f-e486-44ba-b343-c321801cc724/",
        "location_type": {
          "id": "e792af80-ce55-40b0-a042-966e4bd1e21c",
          "url": "http://localhost:8080/api/dcim/location-types/e792af80-ce55-40b0-a042-966e4bd1e21c/"
        }
      },
      {
        "id": "05f86cb2-8494-46ff-8e17-791e9e0ab622",
        "name": "Floor-03",
        "url": "http://localhost:8080/api/dcim/locations/05f86cb2-8494-46ff-8e17-791e9e0ab622/",
        "location_type": {
          "id": "31e5ae94-e963-441b-9869-dfa0a260eff8",
          "url": "http://localhost:8080/api/dcim/location-types/31e5ae94-e963-441b-9869-dfa0a260eff8/"
        }
      },
      {
        "id": "a3567e45-d337-471a-bc6c-6f9cf7ec1bd2",
        "name": "Room-04",
        "url": "http://localhost:8080/api/dcim/locations/a3567e45-d337-471a-bc6c-6f9cf7ec1bd2/",
        "location_type": {
          "id": "d5eeefca-8472-463e-acf0-b76081c3d83e",
          "url": "http://localhost:8080/api/dcim/location-types/d5eeefca-8472-463e-acf0-b76081c3d83e/"
        }
      },
      {
        "id": "40cf88d3-fd59-405d-bc83-a78c69ae7628",
        "name": "Aisle-05",
        "url": "http://localhost:8080/api/dcim/locations/40cf88d3-fd59-405d-bc83-a78c69ae7628/",
        "location_type": {
          "id": "fc71791f-4f85-4e98-a286-bccb9fcd2f6e",
          "url": "http://localhost:8080/api/dcim/location-types/fc71791f-4f85-4e98-a286-bccb9fcd2f6e/"
        }
      },
      {
        "id": "4989eaaa-4b6a-4448-b709-fbdc51c44122",
        "name": "Aisle-12",
        "url": "http://localhost:8080/api/dcim/locations/4989eaaa-4b6a-4448-b709-fbdc51c44122/",
        "location_type": {
          "id": "fc71791f-4f85-4e98-a286-bccb9fcd2f6e",
          "url": "http://localhost:8080/api/dcim/location-types/fc71791f-4f85-4e98-a286-bccb9fcd2f6e/"
        }
      },
      {
        "id": "24136081-cfd0-40ec-ad4d-18784716448c",
        "name": "Room-11",
        "url": "http://localhost:8080/api/dcim/locations/24136081-cfd0-40ec-ad4d-18784716448c/",
        "location_type": {
          "id": "d5eeefca-8472-463e-acf0-b76081c3d83e",
          "url": "http://localhost:8080/api/dcim/location-types/d5eeefca-8472-463e-acf0-b76081c3d83e/"
        }
      },
      {
        "id": "0cdee39e-b5bb-4189-a387-fbdbe947c0df",
        "name": "Aisle-19",
        "url": "http://localhost:8080/api/dcim/locations/0cdee39e-b5bb-4189-a387-fbdbe947c0df/",
        "location_type": {
          "id": "fc71791f-4f85-4e98-a286-bccb9fcd2f6e",
          "url": "http://localhost:8080/api/dcim/location-types/fc71791f-4f85-4e98-a286-bccb9fcd2f6e/"
        }
      },
      {
        "id": "e712e8e3-b56a-4945-93b0-0f92a469c350",
        "name": "Floor-10",
        "url": "http://localhost:8080/api/dcim/locations/e712e8e3-b56a-4945-93b0-0f92a469c350/",
        "location_type": {
          "id": "31e5ae94-e963-441b-9869-dfa0a260eff8",
          "url": "http://localhost:8080/api/dcim/location-types/31e5ae94-e963-441b-9869-dfa0a260eff8/"
        }
      },
      {
        "id": "b243f5bf-fafa-40df-b3a0-67ef12e6cd30",
        "name": "Building-08",
        "url": "http://localhost:8080/api/dcim/locations/b243f5bf-fafa-40df-b3a0-67ef12e6cd30/",
        "location_type": {
          "id": "147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7",
          "url": "http://localhost:8080/api/dcim/location-types/147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7/"
        }
      },
      {
        "id": "a1ac11ce-c846-41cf-a6eb-899835334310",
        "name": "Floor-17",
        "url": "http://localhost:8080/api/dcim/locations/a1ac11ce-c846-41cf-a6eb-899835334310/",
        "location_type": {
          "id": "31e5ae94-e963-441b-9869-dfa0a260eff8",
          "url": "http://localhost:8080/api/dcim/location-types/31e5ae94-e963-441b-9869-dfa0a260eff8/"
        }
      },
      {
        "id": "d8453f8e-4f02-401d-8b28-fc4266139fb1",
        "name": "Room-18",
        "url": "http://localhost:8080/api/dcim/locations/d8453f8e-4f02-401d-8b28-fc4266139fb1/",
        "location_type": {
          "id": "d5eeefca-8472-463e-acf0-b76081c3d83e",
          "url": "http://localhost:8080/api/dcim/location-types/d5eeefca-8472-463e-acf0-b76081c3d83e/"
        }
      },
      {
        "id": "79865f2c-e354-4a04-978a-f0351fe46a38",
        "name": "Campus-14",
        "url": "http://localhost:8080/api/dcim/locations/79865f2c-e354-4a04-978a-f0351fe46a38/",
        "location_type": {
          "id": "83494c52-116f-47ff-9cfb-c42b7f9dda65",
          "url": "http://localhost:8080/api/dcim/location-types/83494c52-116f-47ff-9cfb-c42b7f9dda65/"
        }
      },
      {
        "id": "0a3d9bf5-bf83-43d1-ad1d-243ee869db7b",
        "name": "Building-15",
        "url": "http://localhost:8080/api/dcim/locations/0a3d9bf5-bf83-43d1-ad1d-243ee869db7b/",
        "location_type": {
          "id": "147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7",
          "url": "http://localhost:8080/api/dcim/location-types/147cf6c8-4af5-4e0a-85c5-2de1cf6d3bd7/"
        }
      },
      {
        "id": "35404f7a-8b78-4f83-a98d-70ca646cc57c",
        "name": "Campus-07",
        "url": "http://localhost:8080/api/dcim/locations/35404f7a-8b78-4f83-a98d-70ca646cc57c/",
        "location_type": {
          "id": "83494c52-116f-47ff-9cfb-c42b7f9dda65",
          "url": "http://localhost:8080/api/dcim/location-types/83494c52-116f-47ff-9cfb-c42b7f9dda65/"
        }
      },
      {
        "id": "a7076f77-9e45-4104-8aaa-e83bdfb82cde",
        "name": "Root-06",
        "url": "http://localhost:8080/api/dcim/locations/a7076f77-9e45-4104-8aaa-e83bdfb82cde/",
        "location_type": {
          "id": "6cf5b3f7-540f-48be-b3cb-8c7beaf5cf17",
          "url": "http://localhost:8080/api/dcim/location-types/6cf5b3f7-540f-48be-b3cb-8c7beaf5cf17/"
        }
      },
      {
        "id": "eb40a97a-7366-4819-91db-cb3318489fde",
        "name": "Root-13",
        "url": "http://localhost:8080/api/dcim/locations/eb40a97a-7366-4819-91db-cb3318489fde/",
        "location_type": {
          "id": "6cf5b3f7-540f-48be-b3cb-8c7beaf5cf17",
          "url": "http://localhost:8080/api/dcim/location-types/6cf5b3f7-540f-48be-b3cb-8c7beaf5cf17/"
        }
      }
    ]
  }
}

nautobot/docs/plugins/development.md Outdated Show resolved Hide resolved
@@ -903,9 +903,12 @@ class Animal(BaseModel):

#### Creating Your Own GraphQL Type Object

+/- 1.6.1
A new base class was introduced for Nautobot GraphQL object types: `nautobot.core.graphql.types.OptimizedNautobotObjectType`. This class inherits from `graphene_django_optimizer.OptimizedDjangoObjectType` and adds generic Nautobot specific functionality.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also have some verbiage steering developers to use this as their base class?

Suggested change
A new base class was introduced for Nautobot GraphQL object types: `nautobot.core.graphql.types.OptimizedNautobotObjectType`. This class inherits from `graphene_django_optimizer.OptimizedDjangoObjectType` and adds generic Nautobot specific functionality.
A new base class was introduced for Nautobot GraphQL object types: `nautobot.core.graphql.types.OptimizedNautobotObjectType`. This class inherits from `graphene_django_optimizer.OptimizedDjangoObjectType` and adds generic Nautobot specific functionality. All Nautobot GraphQL object types should inherit from this base class.

gsnider2195 and others added 2 commits August 22, 2023 13:11
@gsnider2195 gsnider2195 merged commit e7704bb into nautobot:develop Aug 22, 2023
17 checks passed
@bryanculver bryanculver added the type: feature Introduction of new or enhanced functionality to the application label Aug 28, 2023
@jamesharr
Copy link
Contributor Author

BTW - TY to everyone who's fixed issues introduced by this PR.

I got busy with work and this kind of fell by the wayside.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature Introduction of new or enhanced functionality to the application
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add url field to GraphQL types
5 participants