7

我正在尝试从 rawqueryset 创建一个查询集,但更改列表总是说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.

这是我的尝试(是一个简单的查询,但它会变得更加复杂,我需要一个原始 SQL 查询):

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

有什么方法可以在我应用admin.site.register(MyModel, MyModelAdmin)在 admin.py 中的更改列表视图中显示这个原始查询?

4

2 回答 2

7

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,

于 2013-11-07T14:02:16.020 回答
1

您可以子类models.Manager化并创建一个执行原始 SQL 的方法,作为 where 子句中的子查询。

https://gist.github.com/carymrobbins/8477219

于 2014-01-17T17:11:33.807 回答