Должен ли я подклассифицировать свою модель 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 и будет иметь свои собственные поля. .

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

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

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

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

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

Ответ принят как подходящий

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

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

Например, добавьте новое поле (updated_at). Почему я должен добавить поле update_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}"

Спасибо. Ваш пример имеет большой смысл. Что касается вашего вопроса об избыточности, абстрактный родительский класс был моей попыткой справиться с этим. Т.е. поместите все общие поля в родительский класс. Однако у меня есть один вопрос: разве это не плохая практика проектирования БД — иметь нулевые поля? В вашем примере post_title и parent_post довольно часто могут иметь значение null. Не будет ли это проблемой?

Shiny_and_Chrome 12.06.2024 13:56

С моей точки зрения, объединение ThreadPost и ReplyPost в единую модель эффективно снижает избыточность. Такой подход сводит к минимуму необходимость обновления нескольких моделей при добавлении новых полей, обеспечивая единый источник достоверной информации и упрощая запросы. Хотя нулевых полей обычно избегают, в нашем случае это компромисс, который упрощает процесс разработки и запроса. Современные базы данных эффективно обрабатывают нулевые значения, поэтому влияние на производительность, вероятно, незначительно. Кроме того, сохраняется целостность данных: значение post_title, равное нулю, указывает на ответ, а значение Parent_post, равное нулю, указывает на публикацию в теме.

Mahrez BenHamad 12.06.2024 15:48

Другие вопросы по теме