我是否应该子类化我的 Django 模型?

问题描述 投票:0回答:2

我正在创建一个简单的论坛应用程序来学习 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 django database
2个回答
0
投票

在考虑是否对 Django 模型进行子类化时,很大程度上取决于您的具体场景,需要更多细节才能给出准确的建议。

该决定应基于您在申请中的观点类型。

例如,如果您需要列出所有线程帖子,那么使用

ThreadPost.objects.all()
检索所有 ThreadPost 对象会很方便。

此外,如果

one-to-many
ThreadPost
之间存在
QueryPost
关系,则最好将这两个放在单独的表中。随着项目规模的扩大,这可以帮助最大限度地减少数据库扫描时间。

相反,添加引用两个不同表的反应模型可能会很复杂且难以管理。

我建议考虑您的观点并为您的项目创建一个粗略的 UI/业务框架。这种方法将帮助您在最终创建所需的模型之前有效地标准化表格。


0
投票

我将给您快速回顾一下建议的代码,然后让我们从缺点问题开始:

  • 当您有两个单独的模型(
    ThreadPost
    ReplyPost
    )时,添加新字段意味着将其添加到两个模型中,明白吗?

例如,添加一个新字段 (

updated_at
)。 为什么我必须在
ThreadPost
ReplyPost
中添加 Updated_at 字段? 我不能避免这种冗余吗?

  • 我正在考虑查询以获取线程中的所有帖子,这有点复杂,因为我需要在查询中分别处理
    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}"
© www.soinside.com 2019 - 2024. All rights reserved.