【发布时间】:2018-04-25 15:52:18
【问题描述】:
如何注释 Django ORM 查询集中的对象,以便每个项目都包含之前(上一个)和之后(下一个)对象的 ID?我正在使用 PostgreSQL 和 Django 1.11。
【问题讨论】:
标签: django postgresql orm
如何注释 Django ORM 查询集中的对象,以便每个项目都包含之前(上一个)和之后(下一个)对象的 ID?我正在使用 PostgreSQL 和 Django 1.11。
【问题讨论】:
标签: django postgresql orm
我认为 Django 范围内稍微更详细的示例可能会对某人有所帮助。查看官方文档here
我在视图中使用它并简单地更新响应对象:
response_data = {}
user = request.user
# put any data in this dict according to the
# logic you have in your view
response_data.update({
"previous_object":
get_next_or_previous_object(user, serializer.data, next_obj=False),
"next_object":
get_next_or_previous_object(user, serializer.data, next_obj=True),
})
def get_next_or_previous_object(user, data, next_obj=None):
"""
Get the previous or next object from the given data list.
If it is not possible to get the object returns None
:param data: List of objects from which the previous or next object
will be taken. OrderedDict and not queryset.
:param bool next_obj: whether the next object should be returned or
the previous one. True = next, False = previous
:return: the previous/next object or None
"""
# Get datetime field name which will be used for obtaining the
# next/previous object
datetime_field_name = MyView.datetime_field_name
object_index = 0 if next_obj else -1
# Get the original object by its id
try:
object_id = data[object_index]["id"]
except (IndexError, KeyError):
object_id = None
try:
parent_object = MyModel.objects.get(id=object_id)
if next_obj:
# Example of the method name: get_next_by_my_timestamp_field
next_method = getattr(
MyModel, f"get_next_by_{datetime_field_name}")
object_to_get = next_method(
parent_object, user=user)
else:
# Example of the method name: get_previous_by_my_timestamp_field
previous_method = getattr(
MyModel, f"get_previous_by_{datetime_field_name}")
object_to_get = previous_method(
parent_object, user=user)
serializer = MyView.serializer_class(object_to_get)
previous_next_object = serializer.data
except MyModel.DoesNotExist:
previous_next_object = None
return previous_next_object
【讨论】:
你可以使用window functions lag() and lead():
SELECT *
, lag(id) OVER (ORDER BY id) AS prev_id -- same order as query
, lead(id) OVER (ORDER BY id) AS next_id -- same order as query
FROM tbl
ORDER BY id;
【讨论】: