根据发布日期在同一页面显示来自不同模型的对象 [英] Display objects from different models at the same page according to their published date

查看:27
本文介绍了根据发布日期在同一页面显示来自不同模型的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have three different models for my app. All are working as I expected.

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)

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

Now I am displaying each of them at separate page for each of the model (e.g. in the jobs page, I am displaying only the jobs.). But now at the home page, I want to display these according to their published date at the same page. How can I display different objects from different models at the same page? Do I make a separate model e.g. class Post and then use signal to create a new post whenever a new object is created from Tender, or Job, or News? I really hope there is a better way to achieve this. Or do I use multi-table inheritance? Please help me. Thank you.

更新:

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

I don't want to show each of the model objects separately at the same page. But like feeds of facebook or any other social media. Suppose in fb, any post (be it an image, status, share) are all displayed together within the home page. Likewise in my case, suppose a new Job object was created, and after that a new News object is created. Then, I want to show the News object first, and then the Job object, and so on.

推荐答案

一个可行的解决方案

有两个可行的解决方案,另外两个答案.两者都涉及三个查询.您正在使用 .all() 查询整个表.这些查询的结果合并到一个列表中.如果每个表都有大约 10k 条记录,这会给 wsgi 服务器和数据库带来巨大压力.即使每个表只有 100 条记录,您也会在视图中不必要地循环 300 次.总之反应慢.

A working solution

There are two working solutions two other answers. Both those involve three queries. And you are querying the entire table with .all(). The results of these queries combined together into a single list. If each of your tables has about 10k records, this is going to put enormous strain on both your wsgi server and your database. Even if each table has only 100 records each, you are needlessly looping 300 times in your view. In short slow response.

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

Multi table inheritance is definitely the right way to go if you want a solution that is efficient. Your models might look like this:

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中的所有记录都没有迭代.

The pubdat field is now indexed (refer the new Post model I posted). That makes the query really fast. There is no iteration through all the records in python.

你如何找出模板中的哪个是哪个?像这样的东西.

How do you find out which is which in the template? With something like this.

{% if post.tender %}

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

进一步优化

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

Further Optimization

There is some room in your design to normalize the database. For example it's likely that the same company may post multiple jobs or tenders. As such a company model might come in usefull.

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

How about one without multi table inheritance or multiple database queries? How about a solution where you could even eliminate the overhead of rendering each individual item?

这是由 redis 排序集 提供的.每次保存 PostJobNews 时,对象都会将其添加到 redis 排序集中.

That comes with the courtesy of redis sorted sets. Each time you save a Post, Job or News, object you add it to a redis sorted set.

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中删除它们

Similarly, you need to add a pre_delete to remove them from redis

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

The clear advantage of this method is that you don't need any database queries at all and your models continue to be really simple + you get catching thrown in the mix. If you are on twitter your timeline is probably generated through a mechanism similar to this.

这篇关于根据发布日期在同一页面显示来自不同模型的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆