Search code examples
djangodjango-modelsmanytomanyfield

Making a reading list and confused about ManyToMany relationship between the models - Django


I am making an app where a user can save books to a "reading" list. I have created 2 models to connect to the custom User model(AbstractBaseUser) I have made.

I am learning how to do this and have been reading the docs.

For the book Model this is what I have. I have created a ManyToMany key with the user since I want the books to be able to be added by other users to their lists once it has been inputted into the book database.

Books model.py

class Books(models.Model):
ONESTAR = "BD"
TWOSTAR = "OK"
THREESTAR = "GD"
FOURSTAR = "VG"
FIVESTAR = "EX"
DEFAULT = "NA"
READ  = "RB"
NOT_READ = "NR"
WANT_READ = "WR"

BOOK_REVIEW_CHOICES = (
    (DEFAULT, 'Rate Book'),
    (FIVESTAR, 'Excellent'),
    (FOURSTAR, 'Very Good'),
    (THREESTAR, 'Good'),
    (TWOSTAR,'Okay'),
    (ONESTAR, 'Bad'),
)

READ_BOOKS_CHOICES = (
    (READ,  'Read Book'),
    (NOT_READ, 'Didnt Read Book'),
    (WANT_READ, 'Want To Read')
    )

user = models.ManyToManyField(UsrAccounts, related_name='users')
title = models.CharField(max_length=300)
author = models.CharField(max_length=255)
description = models.CharField(max_length=500)
book_rating = models.CharField(max_length=2,choices=BOOK_REVIEW_CHOICES, default = DEFAULT)
read_status = models.CharField(max_length=2, choices=READ_BOOKS_CHOICES, default = READ)
image = models.ImageField(upload_to = user_directory_path, null= True, blank=True)
date_added = models.DateTimeField(auto_now=False, auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True, auto_now_add=False)

For the list model I have a foreign key for a ManyToOne relationship between a list and user but a ManyToMany between a list and books.

my List Model.py

class MyList(models.Model):
user = models.ForeignKey(
    'accounts.UsrAccounts',
    on_delete=models.CASCADE)
title = models.CharField(max_length=500)
books = models.ManyToManyField(Books, related_name='books')

Did I set this up right?


Solution

  • If I understand you correctly, you should setup M2M field on UserAccount model point to Book model:

    class UserAccount(models.Model):
        reading_list = models.ManyToManyField('Book', blank=True)
    

    If you want to give reading list a title, you should use another model to hold that, like:

    class UserAccount(models.Model):
        reading_list = models.ManyToManyField('Book', through='ReadingList')
    
    class ReadingList(models.Model):
        user = models.ForeignKey('UserAccount')
        title = models.CharField(max_length=100)
        book = models.ForeignKey('Book')
        # some other fields related to a reading list
    

    Django doc about through keyword on M2M field.

    By the way, don't use plural form on model names, django will add plural form when needed.