Django Using order_by with .annotate() and getting

2019-07-22 19:36发布

I have the following data,

enter image description here

This query groups by topicid, and then in each group gets the max date, frequency of posts and counts the number of authors as contributors,

    info_model = InfoModel.objects.values('topicid')
            .annotate( max=Max('date'), freq=Count('postid'),                   
             contributors=Count('author', distinct=True))

This query can then be displayed as follows,

enter image description here

Q.1 (SOLVED) How can I order the rows by date, from most recent down? I did appended .order_by('date') to the query, which seems like the most obvious solution but this produces,

enter image description here

completely changing the 'freq' and 'contributions'.

EDIT: The ordering can be achieved by appending .order_by('-max')

Q.2 How can I display the 'post' for that date? So the post column should display,

ya

see ya

ciao

yoyo

I thought the following should work with {{ item.post }}, but no such luck.

  <table class='table table-striped table-hover'>
        <thead>
          <tr>
            <th>freq</th>
            <th>topicid</th>
            <th>date</th>
            <th>contributors</th>
            <th>post</th>
          </tr>
        </thead>
        <tbody>
          {% for item in info %}
          <tr>
            <td>{{ item.freq }}</td>
            <td>{{ item.topicid }}</td>
            <td>{{ item.max }}</td>
            <td>{{ item.contributors }}</td>
            <td>{{ item.post }}</td>
          </tr>
          {% endfor %}
        </tbody>
      </table>

Thanks,

Edit:

I can get the correct result with raw SQL but can't do it wth a Django query,

info_model = list(InfoModel.objects.raw('SELECT *, 
              max(date),  
              count(postid) AS freq,     
              count(DISTINCT author) AS contributors FROM        
              crudapp_infomodel GROUP BY topicid ORDER BY date DESC'))

I simplified and reposted this problem here Rewrite raw SQL as Django query

1条回答
闹够了就滚
2楼-- · 2019-07-22 20:01

The following view amalgamates two queries to solve the problem,

def info(request):
    info_model = InfoModel.objects.values('topic')
                 .annotate( max=Max('date'), 
                 freq=Count('postid'), 
                 contributors=Count('author', distinct=True))
                 .order_by('-max')

    info2 = InfoModel.objects.all()

    columnlist = []
    for item in info2:
         columnlist.append([item])

    for item in info_model:
        for i in range(len(columnlist)):
            if item['max'] == columnlist[i][0].date:
                item['author'] = columnlist[i][0].author
                item['post'] = columnlist[i][0].post
                print item['max']

    paginator = Paginator(info_model, 20)
    page = request.GET.get('page')
    try:
        info = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        info = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        info = paginator.page(paginator.num_pages)
    return render(request, 'info.html', {'info': info})
查看更多
登录 后发表回答