Search code examples
sqldjangojoinormadmin

Django Admin: Intersection (Natural Inner Join) between Two Models


I'm a Django beginner. I have two models that I would like to display as one table in the Django admin interface. Below are the simplified versions of the models:

class Final_Application_Personal_Detail(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=20)
    id_no = models.CharField(max_length=14)

class Final_Application_Beneficiary_Detail(models.Model):
    user = models.ForeignKey(User)
    beneficiary_name = models.CharField(max_length=20)
    beneficiary_id_no = models.CharField(max_length=14)

I suppose because these two models conceptually form part of one form (a Final_Application form), I could have maybe used Django's formwizard - however, because in reality both personal details and beneficiary details are quite a lot to fill in, I thought I'd want to give the user a chance to fill them in separately (in django formwizard, as far as I know, if the user doesn't fill out all the data at once, then all previous data is also lost because the form can't be saved with unvalidated fields).

I want to join the two models in Django admin so that the administrative user can see all a user's information (personal details and beneficiary's details) on one page. So, I'd like to do an inner join on the above-mentioned tables on the field 'user'. The SQL would look like this:

SELECT *
FROM Final_Application_Personal_Detail
  JOIN Final_Application_Beneficiary_Detail
  ON Final_Application_Personal_Detail.user = Final_Application_Beneficiary_Detail.user

With regards to Django's ORM, I've looked into the keyword argument related_to in order to join the tables. I don't think that will work, however...it seems as if 'select_related' is just another way to stipulate a foreign key. I now want to use raw SQL in order to join the tables. I've tried using the cursor function to implement raw SQL, but I don't quite know how to implement it so that the output shows in Django's admin interface. Also, I'm a little bit afraid of using raw SQL, because as far as I understand, raw SQL can introduce security risks (I've read that Django's ORM prevents SQL injections).

Thank you for your help.


Solution

  • You can't do this with django admin. However, you can use inlines to edit both models in the User admin.

    from django.contrib import admin
    from django.contrib.auth.models import User
    from django.contrib.auth.admin import UserAdmin
    
    class Final_Application_Personal_DetailInline(admin.StackedInline):
        model = Final_Final_Applicationl_Detail
    
    class Final_Application_Beneficiary_DetailInline(admin.StackedInline):
        model = Final_Final_Application_Beneficiary_Detail
    
    admin.site.unregister(User)
    
    @admin.register(User)
    class CustomUserAdmin(UserAdmin):
        inlines = [
            Final_Application_Personal_DetailInline,
            Final_Application_Beneficiary_DetailInline,
        ]