0

I need to create a field that count the number of registered books of each own library.

Each book is related to a library by a ForeighKey

If I register or delete a book it should update automatically in a "book_count" field related to your own library.

libraries/models.py

from django.db import models

class Libraries(models.Model):
    name = models.CharField(max_length=50)
    book_count = models.IntegerField(default=0)

    def __str__(self):
        return self.name

books/models.py

from django.db import models

from libraries.models import Libraries

class Books(models.Model):
    library = models.ForeignKey(Libraries, on_delete=models.DO_NOTHING, blank=True, null=True)
    book = models.CharField(max_length=200, null=True, blank=True)

    def __str__(self):
        return self.book

How can I create this simple book counter in the model of each library?

8
  • I would use the model name Library for most contexts. Also you have a circular import. Commented Nov 27, 2019 at 21:45
  • Does this answer your question? Django - Circular model import issue Commented Nov 27, 2019 at 21:45
  • I resolved the circular model problem, but the counter didn't work. I edited the post to make it easier. Commented Nov 27, 2019 at 22:19
  • I still see from books.models import Books Commented Nov 27, 2019 at 22:21
  • 1
    Now have no error message. But I need know How can I create a field to book count, in the model of each library? Commented Nov 27, 2019 at 22:42

2 Answers 2

2

Given the following app

$ tree -L 2
.
├── db.sqlite3
├── libraryapp
│   ├── __init__.py
│   ├── __pycache__
│   ├── admin.py
│   ├── migrations
│   ├── models.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py    

and your models (I've done a small bit of refactoring)

$ cat libraryapp/models.py 
from django.db import models

class Library(models.Model):
    name = models.CharField(max_length=50)
    book_count = models.IntegerField(default=0)

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    library = models.ForeignKey(Library, on_delete=models.DO_NOTHING, blank=True, null=True)

    def __str__(self):
        return self.name

    def save(self):
        super().save()
        self.update_book_count()

    def delete(self):
        super().delete()
        self.update_book_count()

    def update_book_count(self):
        if self.library:
            self.library.book_count = self.library.book_set.count()
            self.library.save()

you can get the count of books in a certain library as follows:

$ python3 manage.py shell
>>> from libraryapp.models import Book, Library
>>> library = Library.objects.first()
>>> library.book_count
1

Note that this assumes the only way to update the book count of a library is through adding or deleting a book.

Sign up to request clarification or add additional context in comments.

6 Comments

I can not do this refactoring. I am already finalizing the project and it would be a very difficult change. And "book_count" must be in a field of libreries/models.py. It will be register in DB.
You could make book_count a property. See my edit above.
But you exclude "book_count" field from Library class. Didn't work. Because I need the IntegerField to be automatically completed/edit by the book count.
Fair enough. Please see my edit above. Note that I find this less elegant of a design but given how I'm unaware of the rest of the app maybe it is necessary.
I got it using Signals.
|
1

I got it using Signals.

@receiver(post_save, sender=Book)
def add_book_count(instance, created, **kwargs):
    if created:
        instance.library.book_count += 1
        instance.library.save()


@receiver(post_delete, sender=Book)
def rem_statement_count(instance, **kwargs):
    instance.library.book_count -= 1
    instance.library.save()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.