Должен ли я создавать подклассы для своей модели Django или нет?

Я создаю простое приложение для форума, чтобы изучить Django. Идея состоит в том, чтобы со временем создать полноценный форум, но пока вот что у меня есть:

class Post(models.Model):
    post_body = models.TextField(max_length=2000)
    publish_date = models.DateTimeField("date posted")
    author = models.TextField(max_length=200)  # link to User model later

    class Meta:
        abstract = True

# Post that starts a thread
class ThreadPost(Post):
    post_title = models.Charfield(200)
    is_solved = models.BooleanField("is_issue_solved", default=False)

class ReplyPost(Post):
    is_solution = models.BooleanField("is_this_the_solution", default=False)
    thread_post = models.ForeignKey(ThreadPost, on_delete=models.CASCADE)

Я не уверен, не переборщил ли я с этим. ThreadPost и ReplyPost настолько похожи. Стоит ли мне вместо этого просто создать два отдельных класса, не связанных между собой наследованием?

Можно ли иметь только один класс Post и сделать класс post_title необязательным, если это ответ? Я полагаю, что в этом случае класс Post должен иметь рекурсивное отношение (от 0 до N).

Кроме того, в будущем я хочу добавить другие функции, такие как реакция (например, большие пальцы вверх/вниз, смех и т.д.), возможность сообщить о сообщении и т.д. Что, я думаю, может быть отдельной моделью, которая свяжет Post и User и будет иметь свои собственные поля.

Интересно, какой подход будет наилучшим, чтобы сохранить гибкость моделей для будущих улучшений.

При рассмотрении вопроса о том, стоит ли подклассифицировать вашу модель Django, это во многом зависит от вашего конкретного сценария, и чтобы дать точную рекомендацию, необходимо больше деталей.

Решение должно быть основано на типах представлений, которые будут использоваться в вашем приложении.

Например, если вам нужно перечислить все сообщения темы, будет удобно использовать ThreadPost.objects.all() для получения всех объектов ThreadPost.

Более того, если у вас есть отношения one-to-many между ThreadPost и QueryPost, возможно, лучше хранить их в отдельных таблицах. Это поможет свести к минимуму время сканирования базы данных при масштабировании проекта.

И наоборот, добавление модели реакции, которая ссылается на две разные таблицы, может быть запутанным и сложным в управлении.

Я предлагаю подумать о представлениях и создать примерный UI/бизнес-скелет вашего проекта. Такой подход поможет вам эффективно нормализовать таблицы перед окончательным созданием необходимых моделей.

Я проведу краткий обзор предложенного кода, и начнем с вопросов о недостатках:

  • Когда у вас есть две отдельные модели (ThreadPost и ReplyPost), добавление нового поля означает его добавление в обе модели, вы поняли?

Например, добавьте новое поле (updated_at). Почему я должен добавлять поле updated_at и в ThreadPost, и в ReplyPost? Разве я не могу избежать этой избыточности?

  • Я думаю о запросе для получения всех сообщений в теме, это немного сложно, потому что мне нужно обрабатывать ThreadPost и ReplyPost отдельно в запросах
  • .

И для этого я должен написать:

thread = ThreadPost.objects.get(id=1)
replies = ReplyPost.objects.filter(thread_post=thread)

В том же контексте, что касается получения всех сообщений обоих типов (ThreadPost и ReplyPost), мне нужно написать:

thread_posts = ThreadPost.objects.all()
reply_posts = ReplyPost.objects.all()

Это мой первый и быстрый обзор, и для снастей, которые, по моему мнению, модели будут примерно следующими:

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

class Post(models.Model):
    post_title = models.CharField(max_length=200, blank=True, null=True)  
    post_body = models.TextField(max_length=2000)
    publish_date = models.DateTimeField("date posted", auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    parent_post = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
    is_solved = models.BooleanField("is_issue_solved", default=False)
    is_solution = models.BooleanField("is_this_the_solution", default=False)

    def __str__(self):
        return self.post_title or self.post_body[:30]

    @property
    def is_thread(self):
        return self.parent_post is None

    @property
    def is_reply(self):
        return self.parent_post is not None


class Reaction(models.Model):
    REACTION_CHOICES = [
        ('thumbs_up', 'Thumbs Up'),
        ('thumbs_down', 'Thumbs Down'),
        ('laugh', 'Laugh'),
        # ...
    ]
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    reaction_type = models.CharField(max_length=20, choices=REACTION_CHOICES)

    def __str__(self):
        return f"{self.user.username} - {self.reaction_type}"

class Report(models.Model):
    REPORT_CHOICES = [
        ('spam', 'Spam'),
        ('abusive', 'Abusive Content'),
        # ...
    ]
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    reason = models.CharField(max_length=20, choices=REPORT_CHOICES)
    report_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user.username} reported {self.post.id} for {self.reason}"
Вернуться на верх