Home > front end >  Is it possible to use a related field as a choice field in Django?
Is it possible to use a related field as a choice field in Django?

Time:02-25

In Django, if I have something like this:

class Library(models.Model):
    name = models.CharField(...)
    address = models.CharField(...)
    book_of_the_week = ?

class Book(models.Model):
    library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name="books")
    name = models.CharField(...)

This gives me the ability to create multiple libraries, each with a large number of books.

For book_of_the_week, I want this to be a reference to a Book instance, so that in Django Admin, the field is represented as a dropdown that lets you select from the books in the current library, and in code, you can use .book_of_the_week to access a specific instance of Book.

Is this possible?

CodePudding user response:

Sure, it's possible. But if you do this, you'll only ever be able to save the current book of the week. What happens if you want to show a library's book-of-the-week history? Seems like a likely scenario to me. Consider doing something like:

class Library(models.Model):
    name = models.CharField(...)
    address = models.CharField(...)
    book_of_the_week = ?

class Book(models.Model):
    library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name="books")
    name = models.CharField(...)

class BookOfTheWeek(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='book_of_the_week')
    library = models.ForeignKey(Library, ...etc)
    week_of = models.DateField()

In this manner every book of the week will be a discrete database record, and you'll be able to track a history of each library's book of the week over time.

However...

That said, if you do not need to do this and a single instance record is fine, you should be able to create a ForeignKey relation from Library to Book. However, you may run into some circular and/or hierarchical reference issues depending on how where your model classes are written. In the example you show above, you'd need to declare your ForeignKey model name as a string, like so:

book_of_the_week = models.ForeignKey('Book', on_delete ... etc)

instead of:

book_of_the_week = models.ForeignKey(Book, on_delete ... etc)

...otherwise Django will throw an error because the Book model class is referenced before it is defined. Making 'Book' a string will let Django parse the full models.py file, build the logic, and avoid the error.

Sidenote:

Depending on your specific case you may also consider a ForeignKey to self, like so:

class Book(models.Model):
    library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name="books")
    name = models.CharField(...)
    book_of_the_week = models.ForeignKey('self', on_delete=models.SET_NULL, ...etc)

This would allow any Book on the database table to reference another single Book instance.

  • Related