django - 根据发布日期在同一页面显示来自不同模型的对象

标签 django django-models django-templates django-views

我的应用程序有三种不同的模型。一切都按我的预期工作。

class Tender(models.Model):
    title = models.CharField(max_length=256)
    description = models.TextField()
    department = models.CharField(max_length=50)
    address = models.CharField(max_length=50)
    nature_of_work = models.CharField(choices=WORK_NATURE, max_length=1)
    period_of_completion = models.DateField()
    pubdat = models.DateTimeField(default=timezone.now)    

class Job(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    title = models.CharField(max_length=256)
    qualification = models.CharField(max_length=256)
    interview_type = models.CharField(max_length=2, choices=INTERVIEW_TYPE)
    type_of_job = models.CharField(max_length=1, choices=JOB_TYPE)
    number_of_vacancies = models.IntegerField()
    employer = models.CharField(max_length=50)
    salary = models.IntegerField()    
    pubdat = models.DateTimeField(default=timezone.now)

class News(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    title = models.CharField(max_length=150)
    body = models.TextField()
    pubdat = models.DateTimeField(default=timezone.now)

现在我在每个模型的单独页面上显示它们中的每一个(例如,在工作页面中,我只显示工作。)。但是现在在主页上,我想根据它们在同一页面上的发布日期来显示这些。如何在同一页面上显示来自不同模型的不同对象?我是否制作了一个单独的模型,例如class Post然后每当从 Tender 创建新对象时使用信号创建新帖子, 或 Job , 或 News ?我真的希望有更好的方法来实现这一目标。还是我使用多表继承?请帮帮我。谢谢。

更新:

我不想在同一页面上分别显示每个模型对象。但就像 facebook 或任何其他社交媒体的提要一样。假设在 fb 中,任何帖子(无论是图像、状态、分享)都一起显示在主页中。同样在我的情况下,假设创建了一个新的 Job 对象,然后创建了一个新的 News 对象。然后,我想先显示 News 对象,然后显示 Job 对象,依此类推。

最佳答案

一个有效的解决方案

有两个工作解决方案两个其他答案。这两个都涉及三个查询。您正在使用 .all() 查询整个表.这些查询的结果组合成一个列表。如果你的每个表都有大约 10k 条记录,这会给你的 wsgi 服务器和数据库带来巨大的压力。即使每个表只有 100 条记录,您也会在 View 中不必要地循环 300 次。总之 react 慢。

一个有效的工作解决方案。

如果您想要一个高效的解决方案,多表继承绝对是正确的方法。您的模型可能如下所示:

class Post(models.Model):
    title = models.CharField(max_length=256)
    description = models.TextField()
    pubdat = models.DateTimeField(default=timezone.now, db_index = True)    

class Tender(Post):
    department = models.CharField(max_length=50)
    address = models.CharField(max_length=50)
    nature_of_work = models.CharField(choices=WORK_NATURE, max_length=1)
    period_of_completion = models.DateField()

class Job(Post):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    qualification = models.CharField(max_length=256)
    interview_type = models.CharField(max_length=2, choices=INTERVIEW_TYPE)
    type_of_job = models.CharField(max_length=1, choices=JOB_TYPE)
    number_of_vacancies = models.IntegerField()
    employer = models.CharField(max_length=50)
    salary = models.IntegerField()    


class News(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)

    def _get_body(self):
        return self.description

    body = property(_get_body)

现在您的查询很简单
 Post.objects.select_related(
   'job','tender','news').all().order_by('-pubdat')   # you really should slice
pubdat字段现在已编入索引(请参阅我发布的新 Post 模型)。这使得查询非常快。 python中的所有记录都没有迭代。

你如何找出模板中的哪个是哪个?像这样的东西。
{% if post.tender %}

{% else %} 
   {% if post.news %}
   {% else %}
{% else %}

进一步优化

您的设计中有一些空间可以规范化数据库。例如,同一家公司可能会发布多个职位或标书。因此,公司模式可能会派上用场。

一个更有效的解决方案。

一个没有多表继承或多个数据库查询的怎么样?甚至可以消除渲染每个单独项目的开销的解决方案怎么样?

这是由 redis sorted sets 提供的礼貌.每次保存一个 Post , JobNews , 对象您将其添加到 redis 排序集中。
from django.db.models.signals import pre_delete, post_save
from django.forms.models import model_to_dict

@receiver(post_save, sender=News)
@receiver(post_save, sender=Post)
@receiver(post_save, sender=Job)

def add_to_redis(sender, instance, **kwargs):
    rdb = redis.Redis()

    #instead of adding the instance, you can consider adding the 
    #rendered HTML, that ought to save you a few more CPU cycles.

    rdb.zadd(key, instance.pubdat, model_to_dict(instance)

    if (rdb.zcard > 100) : # choose a suitable number
         rdb.zremrangebyrank(key, 0, 100)

同样,你需要添加一个 pre_delete 来将它们从 redis 中删除

这种方法的明显优势是您根本不需要任何数据库查询,并且您的模型仍然非常简单+您会被混入其中。如果您在 twitter 上,您的时间线可能是通过类似于此的机制生成的。

关于django - 根据发布日期在同一页面显示来自不同模型的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37747427/

相关文章:

python - Django ChoiceField 编辑后保存 None 值?

python - django - 乘法和模板

django - 如何确保序列化程序中至少有一个字段不为空?

python - 如何使用 django Rest 框架解析多部分表单数据中的多个文件?

python - 错误 : "Cannot use None as a query value" When trying to paginate with ListView in Django

python - 如何在模型中没有的 django 管理模型表单中包含文件字段

python - django 信号是否也包含在 transaction.atomic 装饰器中?

Django - 用 models.py 覆盖 get_or_create

Django - 如何在 'NOT IN' 中指定 'limit_choices_to' ?

Django:频繁使用 include template 标签——多少才算是太多?