views:

1425

answers:

4

i'd like to use a view i've created in my database as the source for my django-view.

Is this possible, without using custom sql?

****13/02/09 UPDATE*********

Like many of the answers suggest, you can just make your own view in the database and then use it within the API by defining it in models.py.

some warning though:

  • manage.py syncdb will not work anymore
  • the view need the same thing at the start of its name as all the other models(tables) e.g if your app is called "thing" then your view will need to be called thing_$viewname
+5  A: 

As far as I can see you can easily define a Model class for a view and use it like your other views. I just tested it using a Sqlite-based app and it seems to work fine. Just make sure to add a primary key field if your view's "primary key" column is not named 'id' and specify the view's name in the Meta options if your view is not called 'app_classname'.

The only problem is that the "syncdb" command will raise an exception since Django will try to create the table. You can prevent that by defining the 'view models' in a separate Python file, different than models.py. This way, Django will not see them when introspecting models.py to determine the models to create for the app and therefor will not attempt to create the table.

Ferdinand Beyer
Any idea how it would handle calling the save method on it? Some dbms's have updatable views.
Sam Corder
I am not sure. Chances are that Django simply tries to run an INSERT or UPDATE query on the view, but I don't have too much insight in the Django source code :-)
Ferdinand Beyer
A: 

Is it possible to do what you want through model inheritance?

Sam Corder
+2  A: 

We've done this quite extensively in our applications with MySQL to work around the single database limitation of Django. Our application has a couple of databases living in a single MySQL instance. We can achieve cross-database model joins this way as long as we have created views for each table in the "current" database.

As far as inserts/updates into views go, with our use cases, a view is basically a "select * from [db.table];". In other words, we don't do any complex joins or filtering so insert/updates trigger from save() work just fine. If your use case requires such complex joins or extensive filtering, I suspect you won't have any problems for read-only scenarios, but may run into insert/update issues. I think there are some underlying constraints in MySQL that prevent you from updating into views that cross tables, have complex filters, etc.

Anyway, your mileage may vary if you are using a RDBMS other than MySQL, but Django doesn't really care if its sitting on top of a physical table or view. It's going to be the RDBMS that determines whether it actually functions as you expect. As a previous commenter noted, you'll likely be throwing syncdb out the window, although we successfully worked around it with a post-syncdb signal that drops the physical table created by Django and runs our "create view..." command. However, the post-syncdb signal is a bit esoteric in the way it gets triggered, so caveat emptor there as well.

EDIT: Of course by "post-syncdb signal" I mean "post-syncdb listener"

Joe Holloway
+10  A: 

Just an update for those who'll encounter this question (from Google or whatever else)...

Currently Django has a simple "proper way" to define model without managing database tables:

Options.managed

Defaults to True, meaning Django will create the appropriate database tables in syncdb and remove them as part of a reset management command. That is, Django manages the database tables' lifecycles.

If False, no database table creation or deletion operations will be performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means. This is the only difference when managed is False. All other aspects of model handling are exactly the same as normal.

drdaeman
To provide some context; this feature is available in Django 1.1 upwards.