Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django reverse foreign key in admin

I have a Django related question about foreign keys in the admin panel. I'm facing the following situation:

class Driver(models.Model):
    name = models.CharField(max_length=200)
    executable = models.CharField(max_length=200)

class Device(models.Model):
    name = models.CharField(max_length=200)
    bound_driver = models.ForeignKey(Driver)

class DriverAssignment(models.Model):
    device = models.ForeignKey(Device)
    driver = models.ForeignKey(Driver)

Every device needs to have a bound driver (which it uses). DriverAssignment should be the table which shows which driver can be used by which device. So one device can have multiple possibilities of drivers which can be bound. Now i would like to have a dropdown on my admin panel showing all possible drivers for a specific device to select the 'bound_driver'.

How can i do this in Django? This is probably an easy thing for an experienced Django guy. I hope someone can give me a hint since i'm kind of new to Django. Thanks a lot!

like image 706
Devkev Avatar asked Dec 26 '22 09:12

Devkev


2 Answers

For Django >1.8

Use the InlineModelAdmin (docs for 2.2) as explained there:

models.py

from django.db import models

class Author(models.Model):
   name = models.CharField(max_length=100)

class Book(models.Model):
   author = models.ForeignKey(Author, on_delete=models.CASCADE)
   title = models.CharField(max_length=100)

admin.py

from django.contrib import admin

class BookInline(admin.TabularInline):
    model = Book

class AuthorAdmin(admin.ModelAdmin):
    inlines = [
        BookInline,
    ]
like image 160
Risadinha Avatar answered Dec 29 '22 10:12

Risadinha


Change your model Structure to This:

class Driver(models.Model):
    name = models.CharField(max_length=200)
    executable = models.CharField(max_length=200)

class Device(models.Model):
    name = models.CharField(max_length=200)
    bound_driver = models.ForeignKey(Driver, related_name="bound_to")
    available_drivers = models.ManyToManyfield(Driver)

ManyToManyField would do the same work as DriverAssignment Table.

You can add Available drivers in Available drivers field.

But then You would also Want that bound_driver is one of the Available Drivers. This validation you will have to do in forms. For that you have to over-ride Admin forms. See links

Links of Reference:

ManytoMany field: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField

Model Admin (to over-ride admin functionality): https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects

You will have to spend some time reading and implementing if you want ot learn more. :)

OR

If you want to go with the same structure, than you will have to over-ride the form in ModelAdmin see here and Provide you custom form, which will be something like this:

class CustomForm(ModelForm)
  bound_driver = forms.ModelChoiceField(queryset = <your custom queryset that returns only available drivers>, ...)
  class Meta:
    model = Device

https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form

like image 28
Sahil kalra Avatar answered Dec 29 '22 11:12

Sahil kalra