microsoft / mssql-django

The Microsoft Django backend for SQL Server provides a connectivity layer for Django on SQL Server or Azure SQL DB.
Other
338 stars 112 forks source link

explain_format missing in self.query causes django admin app to not work properly #409

Open evan54 opened 2 weeks ago

evan54 commented 2 weeks ago

I came across it when trying to use the admin page on the django app and it always errors out when trying to use DjangoQL as that seems to use this explain function and errors out so you can't actually search for entires in the admin app.

Software versions

models.py

from django.db import models

class MyModel(models.Model):
    name = models.CharField(blank=False, max_length=255)
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['name'],
                condition=models.Q(name__isnull=False),
                name='non_null_name_unique',
            ),
        ]

Database Connection Settings DATABASES = { 'default': { 'ENGINE': 'mssql', 'HOST': my_host, 'NAME': my_name, 'OPTIONS': { 'driver': 'ODBC Driver 17 for SQL Server', 'host_is_server': True, } } }

Problem description and steps to reproduce

ensure you have some entreis in MyModel in

python manage.py shell  # enter shell
from main.models import m
qs = m.MyModel.objects.all()  # or any code to load some objects in a queryset
qs.explain()  # this errors out

Expected behavior and actual behavior qs.explain() shouldn't error out - should get smth like a string with linebreaks as outputs it seems like?

Error message/stack trace

Traceback (most recent call last): File "C:\Users\UserPath.venv\django\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\UserPath.venv\django\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, callback_kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\options.py", line 688, in wrapper return self.admin_site.admin_view(view)(*args, *kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\utils\decorators.py", line 134, in _wrapper_view response = view_func(request, args, kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\views\decorators\cache.py", line 62, in _wrapper_view_func response = view_func(request, *args, kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\sites.py", line 242, in inner return view(request, *args, *kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper return bound_method(args, kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\utils\decorators.py", line 134, in _wrapper_view response = view_func(request, *args, kwargs) File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\options.py", line 1926, in changelist_view cl = self.get_changelist_instance(request) File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\options.py", line 836, in get_changelist_instance return ChangeList( File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\views\main.py", line 122, in init self.queryset = self.get_queryset(request) File "C:\Users\UserPath.venv\django\lib\site-packages\django\contrib\admin\views\main.py", line 529, in get_queryset qs, search_may_have_duplicates = self.model_admin.get_search_results( File "C:\Users\UserPath.venv\django\lib\site-packages\djangoql\admin.py", line 93, in get_search_results explain() File "C:\Users\UserPath.venv\django\lib\site-packages\django\db\models\query.py", line 1281, in explain return self.query.explain(using=self.db, format=format, options) File "C:\Users\UserPath.venv\django\lib\site-packages\django\db\models\sql\query.py", line 610, in explain return "\n".join(compiler.explain_query()) File "C:\Users\UserPath.venv\django\lib\site-packages\django\db\models\sql\compiler.py", line 1611, in explain_query result = list(self.execute_sql()) File "C:\Users\UserPath.venv\django\lib\site-packages\django\db\models\sql\compiler.py", line 1549, in execute_sql sql, params = self.as_sql() File "C:\Users\UserPath.venv\django\lib\site-packages\mssql\compiler.py", line 366, in as_sql self.query.explain_format,

Exception Type: AttributeError at /admin/main/mymodel/ Exception Value: 'Query' object has no attribute 'explain_format'

Any other details that can be helpful I think I was able to fix it by editing line ln 364 (https://github.com/microsoft/mssql-django/blob/dev/mssql/compiler.py#L364) and doing if explain and hasattr(self.query, 'explain_format'): so it only enters if that is available.

Found this which seems to have some similar issues but it's quite old https://github.com/ESSolutions/django-mssql-backend/pull/126/files

mShan0 commented 2 weeks ago

Hi @evan54, thanks for reporting this. We will get this fix merged in for the next release