N
N
nurzhannogerbek2017-05-31 09:46:07
Django
nurzhannogerbek, 2017-05-31 09:46:07

How to sort data model records based on data from other related models?

Hello! Please help me figure it out.
There is a data model Project (Project). Each project has, let's say, sections. To be more precise, the data models (Characterictic, Task) associated with the project. Users can leave comments on objects/records data model Characterictic, Task. Information about comments is stored in the Comment model.
It is necessary to sort (order_by) the list of projects so that the first were those projects in the sections of which the last comment was left.
For example, a comment was left on Task, which belongs to project A. Then, after a while, a comment was left on Characterictic, which belongs to project B. It turns out that when sorting, you need to put Project B first, and project A after it.
models.py:

class Project(models.Model):
    name = models.CharField(_('Name'), max_length=250)
    create_time = models.DateTimeField(auto_now_add=True)  # Дата создания записи
    revision_date = models.DateTimeField(_('Date of last update'), auto_now=True) # Дата последнего обновления записи

class Characteristic(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    description = models.TextField(_('Description'))
    comments = models.ManyToManyField("Comment")
    create_time = models.DateTimeField(auto_now_add=True)
    revision_date = models.DateTimeField(_('Date of last update'), auto_now=True)

class Task(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    description = models.TextField(_('Description'))
    comments = models.ManyToManyField("Comment")
    create_time = models.DateTimeField(auto_now_add=True)
    revision_date = models.DateTimeField(_('Date of last update'), auto_now=True)

class Comment(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    text = models.TextField()
    created = models.DateTimeField(auto_now_add=True)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anatoly Scherbakov, 2017-05-31
@nurzhannogerbek

Not sure how to do it via ORM, need to experiment. If someone offers, it will be interesting to see. If no one offers, then I would do so.

class Characteristic(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='characteristics')
    ...

class Task(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='tasks')
    ...

...

import operator

latest_comments_by_category = Project.objects.values_list('id').annotate(
    Max('characteristics__comments__created'),
    Max('tasks__comments__created'),
)

latest_comments = [
    (project_id, max(characteristic_time, task_time))
    for project_id, characteristic_time, task_time in latest_comments_by_category
]

projects = [
    Projects.objects.get(id=project_id)
    for project_id, _ in sorted(latest_comments, key=operator.itemgetter(1), reverse=True)
]

Of course, this is only acceptable if there are not too many projects.
PS Most likely this is some kind of block of statistics. It can be cached to speed up the page.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question