nautobot / nautobot-app-version-control

Version Control App that uses and requires a Dolt Database
Other
30 stars 6 forks source link

Field Error when creating pull request review #149

Closed tim-fiola closed 2 years ago

tim-fiola commented 2 years ago

Creating a pull request review using the form throws an exception:

<class 'django.core.exceptions.FieldError'>

Cannot resolve keyword 'user' into field. Choices are: id, pull_request, pull_request_id, reviewed_at, reviewer, reviewer_id, state, summary

Python version: 3.6.15
Nautobot version: 1.2.0b1

This is new behavior as this was working perfectly prior.

Here is an example of a pull request review create form: image

When I click the "Create" button, I get this: image

jathanism commented 2 years ago

This issue does not appear in Nautobot v1.1.5.

glennmatthews commented 2 years ago

~I don't see this issue with a local development instance running 1.2.0b1.~

(Edit: I misunderstood the trigger for this issue - can confirm that it's reproducible as described by others below.)

tim-fiola commented 2 years ago

I recreated this problem running 1.2.0b1. Here is the full trace

Environment:

Request Method: POST
Request URL: http://0.0.0.0:8080/plugins/dolt/pull-request/651f03e2-b8a2-4b89-a93f-4eb6b4c47310/reviews/add/

Django Version: 3.1.14
Python Version: 3.6.15
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'cacheops',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'mptt',
 'rest_framework',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotServerConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.utilities',
 'nautobot.virtualization',
 'django_rq',
 'drf_yasg',
 'graphene_django',
 'health_check',
 'health_check.cache',
 'health_check.storage',
 'django_extensions',
 'constance.backends.database',
 'debug_toolbar',
 'dolt.NautobotDolt']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
 'django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'nautobot.core.middleware.ExceptionHandlingMiddleware',
 'nautobot.core.middleware.RemoteUserMiddleware',
 'nautobot.core.middleware.ExternalAuthMiddleware',
 'nautobot.core.middleware.APIVersionMiddleware',
 'nautobot.core.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware',
 'dolt.middleware.dolt_health_check_intercept_middleware',
 'dolt.middleware.DoltBranchMiddleware',
 'dolt.middleware.DoltAutoCommitMiddleware']

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 171, in _get_response
    response = middleware_method(request, callback, callback_args, callback_kwargs)
  File "/source/dolt/middleware.py", line 74, in process_view
    return view_func(request, *view_args, **view_kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/core/views/generic.py", line 312, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/utilities/views.py", line 94, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/source/dolt/views.py", line 758, in post
    return super().post(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/core/views/generic.py", line 336, in post
    obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/core/views/generic.py", line 287, in get_object
    return get_object_or_404(self.queryset, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/shortcuts.py", line 76, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/cacheops/query.py", line 353, in get
    return qs._no_monkey.get(qs, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 418, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 962, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 969, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1360, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1382, in _add_q
    split_subq=split_subq, check_filterable=check_filterable,
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1260, in build_filter
    lookups, parts, reffed_expression = self.solve_lookup_type(arg)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1086, in solve_lookup_type
    _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1484, in names_to_path
    "Choices are: %s" % (name, ", ".join(available)))

Exception Type: FieldError at /plugins/dolt/pull-request/651f03e2-b8a2-4b89-a93f-4eb6b4c47310/reviews/add/
Exception Value: Cannot resolve keyword 'user' into field. Choices are: id, pull_request, pull_request_id, reviewed_at, reviewer, reviewer_id, state, summary
jathanism commented 2 years ago

Confirmed that I am able to reproduce this on develop head (1.2.0b2).

jathanism commented 2 years ago

I narrowed down the issue to be related to this change in nautobot.core.views.generic.ObjectEditView.get_object():

@@ -248,13 +283,23 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):

     def get_object(self, kwargs):
         # Look up an existing object by slug or PK, if provided.
-        if "slug" in kwargs:
-            return get_object_or_404(self.queryset, slug=kwargs["slug"])
-        elif "pk" in kwargs:
-            return get_object_or_404(self.queryset, pk=kwargs["pk"])
-        # Otherwise, return a new instance.
+        if kwargs:
+            return get_object_or_404(self.queryset, **kwargs)
         return self.queryset.model()

If I revert the method to pre-1.2.0 it works.

glennmatthews commented 2 years ago

See also https://github.com/nautobot/nautobot/issues/1098 (another get_object impact). We might need to rework that change.

mzbroch commented 2 years ago

Thanks for looking into this! I reproed it on my sandbox as well.

jathanism commented 2 years ago

Fixed in https://github.com/nautobot/nautobot/pull/1145