Как автоматически обновить атрибут модели при создании другой модели
Я изучал django и django rest на нескольких различных курсах и начал свой собственный проект, который будет представлять собой веб-приложение типа форума.
У меня 4 модельных класса Category, SubCategory, Thread и Post. Я хочу иметь атрибут для подкатегории под названием num_threads, который может быть обновлен, когда создается тема для подкатегории, с которой она связана. Аналогично я хочу, чтобы у темы были атрибуты num_posts и num_views. Я использовал внешние ключи для связи моделей. Теперь я не уверен, что делаю эту часть правильно. Вот мой 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)
У меня есть ссылки в классах моделей, которые присваивают внешний ключ. Есть ли способ автоматически обновлять атрибут модели, когда создается другой объект с внешним ключом. IE: Увеличение подкатегории num_thread, когда создается поток с тем же внешним ключом.
Просматривая другие вопросы здесь, я видел упоминания об использовании пользовательских методов сохранения, но после изучения документации я все еще не уверен, как это будет работать.
Пожалуйста, дайте мне знать, что есть другие ресурсы, которые я мог бы использовать.
Пожалуйста, не храните количество Threads (или любой другой агрегат) в модели. Это форма дублирования данных, которая часто является антипаттерном: это означает, что вам нужно будет реализовать обработчики, когда Threads создаются, обновляются (ссылаются на другой SubCategory) или удаляются. Оказывается, что синхронизация этих обработок часто представляет собой сложную проблему, даже если две таблицы хранятся в одной и той же базе данных.
Вы можете удалить поле num_thread и использовать .annotate(…) [Django-doc] и подсчитывать количество связанных Thread при необходимости с помощью:
from django.db.models import Count
SubCategory.objects.annotate(
num_threads=Count('thread')
)
Объекты SubCategory, происходящие из этого набора запросов, будут иметь дополнительный атрибут .num_threads, содержащий количество связанных Thread объектов.