clokep / django-querysetsequence

Chain multiple (disparate) QuerySets in Django
https://django-querysetsequence.readthedocs.io/
ISC License
107 stars 25 forks source link

Support using `models.F` in `QuerySetSequence.order_by()` #92

Open tui95 opened 2 years ago

tui95 commented 2 years ago

Describe the bug I've tried to use QuerySetSequence.order_by() with models.F, but it fails with the following error message

Internal Server Error: /backend/planning/plans/
Traceback (most recent call last):
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/tui/Desktop/develop/work/pttep/projects/fwlap/fwlap-backend/planning/views/combined_plan_view.py", line 47, in list
    response_objects = plan_list_service.list(
  File "/Users/tui/Desktop/develop/work/pttep/projects/fwlap/fwlap-backend/planning/services/combined_plan_list_service.py", line 22, in list
    combined_plan_queryset = CombinedPlanQuerySet(
  File "/Users/tui/Desktop/develop/work/pttep/projects/fwlap/fwlap-backend/planning/models/plan.py", line 41, in order_by_date_range
    return self.order_by(
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/queryset_sequence/__init__.py", line 780, in order_by
    _, filtered_fields = self._separate_fields(*fields)
  File "/Users/tui/Library/Caches/pypoetry/virtualenvs/fwlap-backend-vuErbnoo-py3.9/lib/python3.9/site-packages/queryset_sequence/__init__.py", line 645, in _separate_fields
    if field.startswith("#") or field.startswith("-#"):
AttributeError: 'OrderBy' object has no attribute 'startswith'

Versions django: 4.0 django-querysetsequence: 0.16

To Reproduce Given two models with a common field.

from django.db import models

class ModelA(models.Model):
    date = models.DateField(null=True)

class ModelB(models.Model):
    date = models.DateField(null=True)

Then calling order_by on QuerySetSequence with models.F will result in error

combined_queryset = QuerySetSequence(
    ModelA.objects.all(),
    ModelB.objects.all(),
).order_by(
    models.F("date").asc(nulls_first=True)
)
print(list(combined_queryset))

Expected behavior QuerySetSequence.order_by() should work with models.F since it's a valid Django code.

clokep commented 2 years ago

I don't think any of the Django expressions currently work with django-querysetsequence, it would likely not be too hard to add, but unsure -- the ordering logic can get a bit hairy.