与 Queryset Values() 有关

Related to Queryset Values()

这段代码工作得很好。但它很慢。所以我想重构下面的代码。

from django.template.defaultfilters import date
json_resp = []
actions = Model.objects.all().select_related('user')

for action in actions:
    json_resp.append({
        'user': some_custom_function(user),
        'created_at': date(action.created_at, 'U')
    })
return HttpResponse(json.dumps(json_resp), content_type='application/json')



def some_custom_function(user):
    # return anonymous if there's no first name.
    if not user.first_name:
        return u'Anonymous'

    # if not last name, return first name.
    if not user.last_name:
        return u'{}'.format(user.first_name)

    # I can't use get_full_name().
    return u'{0} {1}.'.format(user.first_name, user.last_name[:1])

重构代码

actions = Model.objects.all().select_related('user').values(
    'user',
    'created_at'
).order_by('-created_at')

但是有个问题。如果我想对字段执行附加功能怎么办?我可以用 values() 做这个吗?

就像我在第一部分所做的那样。 'created_at': date(action.created_at, 'U').

有没有更好的方法?非常感谢。

编辑: 我可以在 javascript 中移动 some_custom_function 函数。我只关心 date 过滤器。我想我必须使用 extra()

您可以在 values() 方法中使用 __ 关系。要提高速度,请使用 values_list() 而不是值,减少格式化代码并切换到列表理解:

from datetime import datetime

def full_name(first_name, last_name):
    if not first_name:
        return u'Anonymous'
    if not last_name:
        return first_name
    return u'{0} {1}.'.format(first_name, last_name[:1])

def seconds_since_epoch(time):
    return int(time - datetime(1970, 1, 1)).total_seconds())

...

actions = Model.objects.all().select_related('user').values_list(
    'user__first_name', 'user__last_name', 'created_at'
).order_by('-created_at')

json_resp = [{'user': full_name(first_name, last_name),
              'created_at': seconds_since_apoch(created_at)}
             for fist_name, last_name, created_at in actions]