Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return QuerySet from a RawQuerySet

I am trying to create a queryset from a rawqueryset, but the changelist is always saying Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user.

This is my attempt (is a simple query, but it will became more complex and I need a raw SQL query):

class MyModelAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = MyModel.objects.raw('SELECT field1, field2 FROM MyTable)
        return qs

Is there any way to show this raw query in my changelist view applying admin.site.register(MyModel, MyModelAdmin) in admin.py?

like image 908
toscanelli Avatar asked Nov 07 '13 12:11

toscanelli


1 Answers

It's been a while, and versions seem to have changed a lot since then, however you used to be able to simple convert the qs itself to a string or the query attribute contained within the qs, and it would spell out the sql for you.

e.g. sql = str(qs) or sql = str(qs.query)

That being said, django modifies the table names. It's probably not MyTable you're looking for, but appname_my_table. Browse the django core to find out exactly what the naming specification is, or perhaps get it from model_instance._meta.db_name or similar property.

update: ok it seems I misunderstood the question, you don't want to 'print' the queryset to inspect the sql it generates at all, you need the ModelAdmin to pass a RawQuerySet instead of a regular QuerySet to its ChangeView.

Short answer: No, its not going to work that way. They are two very distinct classes.

It looks like they behave the same, because you can iterate them and when you do it turns out to contain proper model instances. However its missing a plethora of other functionality that the ModelAdmin's changeview has come to rely upon over time. I'm not even sure if it actually has a Manager.

The only option that comes to mind, is using either:

  1. Use Model.objects.extra(...) instead of Model.objects.raw(...), so that it returns a proper QuerySet.

  2. Create a view using your database software, Postgres or MySQL, what have you. And map that to a simple django Model.

  3. You can try and recreate all the missing functionality by wrapping the RawQuerySet in a little proxy class that passes everything on to the RawQuerySet and implement the missing methods yourself. I do not recall which those were, probably you need to override __and__ and __or__, provide it with a custom manager, at the very least. I've done this before and its very possible but I guarantee a lot of work, especially if you expect ALL of the usual admin magic to work, think filterspecs, search, inline relationships. Expect to hurt your brain, or learn to live without most of the admins benefits you've come to love.

The thing is, using raw(...) basicly results in being entirely seperated from django's ORM, even though at first glance it fools you into thinking that this is not the case (primarily because its iterator returns proper Model instances). Ofcourse your ModelAdmin's ChangeView has not got the slightest clue of what to do with it.

Kind regards,

like image 79
Yuka Avatar answered Sep 22 '22 09:09

Yuka