Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to auto update a models attribute on creation of another model

I have been learning django and django rest from several different courses and have started my own project which will be a forum type web application.

I 4 model classes Category, SubCategory, Thread, and Post.
What I want to be able to do is have an attribute for subcategory called num_threads that can be updated when ever a thread is made for the subcategory it is related to. Similarly I will want a thread to have attributes num_posts and num_views. I have been using foreign keys to relate the models. Now I am not sure that I am doing that part correctly.
Here is my model.py:

from django.db import models
from django.contrib.auth.models import User


class Category(models.Model):
    """
    Category Class:
    Main Categories for GRDG Forum
    Creation and Deletion will be restricted to site admin
    """

    # Attributes
    name = models.CharField(max_length=32, unique=True, blank=False)
    description = models.TextField(max_length=150, blank=True)

    def __str__(self):
        return self.name


class SubCategory(models.Model):
    """
    SubCategory Class:
    SubCategories will be one to many relation with category ie: Multiple subcategories related to one category
    Creation and Deletion will be restricted to site admin
    GET methods restriction will vary by subcategory
    """

    # References
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    # Attributes
    name = models.CharField(max_length=32, unique=True, blank=False)
    description = models.TextField(max_length=150)
    num_threads = models.IntegerField(max_length=None, default=0)

    def __str__(self):
        return self.name


class Thread(models.Model):
    """
    Class Thread
    Threads will be one to many relation to subcategory ie: Multiple threads related to one subcategory
    Creation and Deletion restricted to authorized and authenticated users
    GET methods restriction will vary by parent subcategory.
    """

    # References
    subcategory = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
    user = models.ForeignKey(User, models.CASCADE)

    # Attributes
    title = models.CharField(max_length=32, unique=False, blank=False)
    num_views = models.IntegerField(max_length=None, default=0)
    num_posts = models.IntegerField(max_length=None, default=0)
    locked = models.BooleanField(default=False)
    author = models.CharField(max_length=32, blank=False)

    def __str__(self):
        return self.title


class Post(models.Model):
    """
    Class Posts
    Posts will be one to many relation to Thread ie: Multiple posts related to one Thread
    Creation and Deletion restricted to authorized and authenticated users
    """

    # References
    thread = models.ForeignKey(Thread, on_delete=models.CASCADE)
    user = models.ForeignKey(SubCategory, on_delete=models.CASCADE)

    # Attributes
    body = models.TextField(max_length=500, blank=False)
    author = models.CharField(max_length=32, blank=False)

I have references in the model classes that assign the foreign key.
Is there a way to automatically update the a models attribute when ever another object with the foreign key is created.
IE: Increased a subcategories num_thread, when a thread with the same foreign key is created.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Looking at other question here I have seen mentions of using custom save methods and after looking at its documentation I am still not sure how it would work.

Please let me know thoughts are other resources I could use.

>Solution :

Please don’t store the number of Threads (or any other aggregate) in a model. This is a form of data duplication which is often an antipattern: it means that you will need to implement handlers when Threads are created, updated (refer to another SubCategory) or removed. It turns out that keeping these in sync is often a hard problem, even if the two tables are stored in the same database.

You can remove the num_thread field and use .annotate(…) [Django-doc] and calculate the number of related Threads when necessary with:

from django.db.models import Count

SubCategory.objects.annotate(
    num_threads=Count('thread')
)

The SubCategorys that originate from this queryset will then have an extra attribute .num_threads that contains the number of related Thread objects.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading