1

Basically, I have issues working with a legacy database where the tables I am using have no proper referential integrity (like no foreign keys; just tables but 'I' know they are related by some columns). So, Django's framework would not be beneficial while querying n tables across m different oracle users.

Something like this: select t1.col1, t2.col3, t3.col2 from user1.table1 t1, user2.table2 t2, user3.table3 t3 where t1.col1 = t2.col2 AND t2.col2 = t3.col3;

And now in Django's Admin UI, I wanted to display this:

---------------------------
| col1  |  col3  |  col2  |
---------------------------
| abcd  |  defg  |  hijk  |
---------------------------
| 1234  |  5678  |  9009  |
---------------------------

I have started on Django for its fast development only very recently. Hence, any support or docs are much appreciated.

Aditya369
  • 545
  • 1
  • 7
  • 27

1 Answers1

3

To take advantage of Django Admin, you need to make a model first, no matter from where it fetches data. Now, since we are mapping the model to DB, you could either make the model based on a DB view, or any one of the three tables(user1.table1, user2.table2 and user3.table3):

Base on DB view:

First, create a DB view to take col1, col2 and col3 from tables.
Also, choose a primary key for the model: it could be any (including extra) column in the DB view, as long as the model field w/ primary_key=True matches the column, here I simply choose col1.

# use Sqlite to create view, Oracle could be similar
CREATE VIEW view_for_legacy_tables AS SELECT t1.col1, t2.col3, t3.col2 from user1.table1 t1, user2.table2 t2, user3.table3 t3 where t1.col1 = t2.col2 AND t2.col2 = t3.col3;

# in model
class Foo(models.Model):
    col1 = models.TextField(primary_key=True)
    col2 = models.TextField()
    col3 = models.TextField()

    class Meta:
        db_table = 'view_for_legacy_tables'

From now on, syncdb or South migrate might complain the exists, here simply ignore them.
You could bypass it by faking migration in South or move the model from models.py to other files or functions that does not loaded by models.py.

After define corresponding ModelAdmin for the model Foo, the Foo could be displayed in changelist in Django Admin.

If you want to use addview or changeview to do some modification upon the tables, you could override save method of the Foo model or customize ModelForm, or customize add_view/change_view of the ModelAdmin. The code varies on your actual usage, thus I don't provide one here.

Base on table user1.table1

This works similar as the method based on DB view. To be able to use addview and changeview, you need to customize ModelForm also.

Define the model

class Foo(models.Model):
    col1 = models.TextField(primary_key=True)

    class Meta:
        db_table = 'user1.table1'

Then in admin.py

class FooAdmin(admin.ModelAdmin):
    list_display = ('col1', 'col2', 'col3')

    def queryset(self, request): # you could customize the default manager of model Foo
        qs = super(FooAdmin, self).queryset(request)
        return qs.extra(select={'col2':'user2.table2.col2', 'col3':'user3.table3.col3'},
                        tables=['user2.table2', 'user3.table3'],
                        where=['col1 = user2.table2.col2', 'user2.table2.col2'='user3.table3.col3']) # or use `raw()`, depends on your columns

    def col2(self, obj):
        return obj.col2

    def col3(self, obj):
        return obj.col3

update

The usage is very uncommon, thus I've seen few documents about it. Most relative things could be options.py inside django/contrib/admin and the implementation of Model inside django/db/models/base.py.

If you want to achieve SELECT * from t1, t2, t3 where ... like '%?%'", [var1]), the easiest way probably is to write your own view by using Admin UI, just as https://github.com/dmpayton/django-mongoadmin

If var1 of SELECT * from t1, t2, t3 where ... like '%?%'", [var1]) is determined, you could make several models for each value of var1; if its not, you have to do some dynamic way about model and admin, just ref Django dynamic model fields , which could be even harder IMO.

Community
  • 1
  • 1
okm
  • 23,575
  • 5
  • 83
  • 90
  • Is there no way to achieve this with out the model class or/and the DB view? like using the `cursor.execute("SELECT * from t1, t2, t3 where ... like '%?%'", [var1])` to achieve this. Plus I like the admin interface, so can i extend the template `change_list.html` for my SQL query? Pls point me to sufficient resources as I am still a newbie.. :( – Aditya369 Apr 30 '12 at 05:59
  • @Aditya369 AFAIK no easier ways, Admin views binds tightly w/ Django Model. You could use monkey patch to mimic an object but it won't be easier than make a model. See the updated part in my answer also. – okm Apr 30 '12 at 08:00