开发者

django join-like expansion of queryset

I have a list of Persons each which have multiple fields that I usually filter what's upon, using the object_list generic view. Each person can have multiple Comments attached to them, each with a datetime and a text string. What I ultimately want to do is have the option to filter comments based on dates.

class Person(models.Model):
    name = models.CharField("Name", max_length=30)
    ## has ~30 other fields, usually filtered on as well

class Comment(models.Model):
    date = models.DateTimeField()
    person = models.ForeignKey(Person)
    comment = models.TextField("Comment Text", max_length=1023)

What I want to do is get a queryset like

Person.objects.filter(comment__date__gt=date(2011,1,1)).order_by('comment__date')

send that queryset to object_list and be able to only see the comments ordered by date with only so many objects on a page.

E.g., if "Person A" has comments 12/12/2010, 1/2/2011, 1/5/2011, "Person B" has no comments, and person C has a comment on 1/3/2010, I would see:

"Person A",   1/2  - comment
"Person C",   1/3  - comment
"Person A",   1/5  - comment

I would strongly prefer not to have to switch to filtering based on Comments.objects.filter(), as that would make me have to largely repeat large sections of code in the both the view and template.

Right now if I tried executing the following command, I will get a queryset returning (PersonA, PersonC, PersonA), but if I try rendering that in a template each persons comment_set will contain all their comments even if they aren't in the date range.

Ideally there would be some sort of functionality where I could expand out a Person queryset's comment_set into a larger queryset that can be sorted and ordered based on the comment and put into a object_list generic view. This normally is fairly simple to do in SQL with a JOIN, but I don't want to abandon the ORM, which I use everywhere else.


OK, my solution was basically just Comments.objects.filter(); split the template into a separate file that is included in the appropriate fashion开发者_如何学JAVA, apply extra context boolean (if comment_date_filter, apply an appropriate prefix string before all person references in the view (that's either '', or 'person__'):

{% if comment_date_filter %}
   {% for obj in object_list %}
      {% with obj.person as p %}
        {% include "object_list_row.html" %}
      {% endwith %}
   {% endfor %}
{% else %}
   {% for obj in object_list %}
      {% with obj as p %}
        {% include "object_list_row.html" %}
      {% endwith %}
   {% endfor %}
{% endif %}


The other option you have is to pull all objects out as (Person, Date, Comment) tuples and sort them in Python.

However, I don't know what your reason for not wanting to use Comment.objects.filter(). This is likely going to be fairly fast, especially if your date field is indexed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜