Home > Software design >  Django 4.0. Updating field once every day
Django 4.0. Updating field once every day

Time:06-08

I have a Book model that has a integer field count which is the number of users that have this book in their readlist. Users can add a book to their ReadList model (many to many field). I want to update the count in the book model once a day...how should I go about doing this?

Will be using this to displaying trending books and book rank based on user count.

Book Model:

class Book(models.Model):
name = models.CharField(max_length=150, unique=True)
description = models.TextField()
user_count = models.IntegerField()
pages = models.IntegerField()
genres = models.ManyToManyField(Genre)

def __str__(self):
    return self.name

ReadList Model:

class ReadList(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
readlist = models.ManyToManyField(Book, related_name='readlist', blank=True)

def __str__(self):
    return self.user.username

CodePudding user response:

Django unfortunately doesn't do scheduling very well. You can actually generate this information already, via the related_name, with the advantage this will be realtime!

Let's start with a queryset for all books. Imagine you put this in one of your views.

books = Book.objects.all()

Now you have all your books, but no data on booklist numbers. So we can annotate that information via the query

from django.db.models import Count
books = Book.objects.all().annotate(user_count = Count('readlist') 

Useful, but in no particular order, lets arrange it from highest to lowest.

books = Book.objects.all().annotate(user_count = Count('readlist') .order_by('-user_count')

But do we want it for every book in the store? Let's limit to the top 10.

books = Book.objects.all().annotate(user_count = Count('readlist') .order_by('-user_count')[:10]

The books don't necessarily know their own place in the heirarchy, though. Lets cycle through them and give them another impromptu field (Querysets aren't really indexed, so we can do this ourselves)

for index, book in enumerate(books):
    book.placing = index

Pass context['books'] = books to your template and you should be able to do the following:

{% for book in books %}
   Title:{{book.title}} <br>
   Position:{{book.placing}} <br>
   In :{{book.user_lists}} reading lists<br>

And there you have it, an up to the minute list of the top 10 books sorted by user_count without having to use external scheduling. Make sure you add the palcing last, as any further DB queries on the queryset will cause the query to be remade.

  • Related