рдирдорд╕реНрддреЗ!
рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд▓рдЧрд╛! рдореИрдВ рдЗрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╕рднреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рд░реЛрдорд╛рдВрдЪрд┐рдд рд╣реВрдВ!
рдЙрд╕рдХреЗ рд▓рд┐рдпреЗ рдЖрдкрдХрд╛ рдзрдиреНрдпрд╡рд╛рдж!
рдореЗрд░рд╛ рд▓рдХреНрд╖реНрдп рдЕрднреА рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдореЙрдбрд▓ рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рдЦреЛрдЬ-рдХреНрд╖рдорддрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╕рд╛рде рд╣реА рд╕рд╛рде рдЖрджреЗрд╢ рджреЗрддрд╛ рд╣реИред
рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ School
рдореЙрдбрд▓ рд╣реИ рдЬрд┐рд╕ рдкрд░ рдПрдХ рдкрд░рд┐рдХрд▓рд┐рдд рдлрд╝реАрд▓реНрдб рд╣реИ рдЬрд┐рд╕реЗ learner_enrolled_count
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
JSON рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:
{
"schools": [
{
"id": 6,
"name": "Piano Gym Six",
"courses": [
// ...
],
"learner_enrolled_count": 0
},
{
"id": 7,
"name": "Piano Gym Seven",
"courses": [
// ...
],
"learner_enrolled_count": 5
}
]
}
learner_enrolled_count
рдПрдХ рдкрд░рд┐рдХрд▓рд┐рдд рдлрд╝реАрд▓реНрдб рд╣реИред
рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рдкреНрд░рд▓реЗрдЦрди рдкрдврд╝рд╛ рд╣реИ:
https://django-filter.readthedocs.io/en/stable/ref/filters.html?highlight=order#orderingfilter
рдФрд░ рдпрд╣рд╛рдБ:
https://django-filter.readthedocs.io/en/stable/ref/filters.html?highlight=order#adding -custom-filter-choices
рддреЛ рдЙрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореИрдВрдиреЗ рдпрд╣ рдлрд╝рд┐рд▓реНрдЯрд░ рд╕реЗрдЯ рдпрд╣рд╛рдБ рд▓рд┐рдЦрд╛ рд╣реИ:
# ------------------------------------------------------------------------------
# Python Standard Libraries
# ------------------------------------------------------------------------------
# N/A
# ------------------------------------------------------------------------------
# Third-party Libraries
# ------------------------------------------------------------------------------
from django_filters import CharFilter
from django_filters import OrderingFilter
from django_filters.rest_framework import FilterSet
# ------------------------------------------------------------------------------
# Custom Libraries
# ------------------------------------------------------------------------------
from piano_gym_api.versions.v1.models.school_model import SchoolModel
# See:
# https://django-filter.readthedocs.io/en/stable/ref/filters.html#adding-custom-filter-choices
class SchoolOrderingFilter(OrderingFilter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.extra["choices"] += [
("learner_enrolled_count", "Learner Enrolled Count"),
("-learner_enrolled_count", "Learner Enrolled Count (descending)"),
]
def filter(self, query_set, values):
if(values is None):
return super().filter(query_set, values)
for value in values:
if value in ['learner_enrolled_count', '-learner_enrolled_count']:
return query_set.order_by(value)
return super().filter(query_set, values)
class SchoolFilter(FilterSet):
school_name = CharFilter(field_name="name",
lookup_expr="icontains")
# ---
course_name = CharFilter(field_name="school_course__name",
lookup_expr="icontains")
course_description = CharFilter(field_name="school_course__description",
lookup_expr="icontains")
# ---
lesson_name = CharFilter(field_name="school_lesson__name",
lookup_expr="icontains")
lesson_description = CharFilter(field_name="school_lesson__description",
lookup_expr="icontains")
# ---
flash_card_set_name = CharFilter(field_name="school_lesson__flash_card_set__name",
lookup_expr="icontains")
flash_card_set_description = CharFilter(field_name="school_lesson__flash_card_set__description",
lookup_expr="icontains")
# ---
headmaster_username = CharFilter(field_name="school_board__school_board_headmaster__learner__user__username",
lookup_expr="icontains")
board_member_username = CharFilter(field_name="school_board__school_board_member__learner__user__username",
lookup_expr="icontains")
# See:
# https://django-filter.readthedocs.io/en/stable/ref/filters.html#orderingfilter
o = SchoolOrderingFilter(
# tuple-mapping retains order
fields=(
("learner_enrolled_count", "learner_enrolled_count"),
),
# labels do not need to retain order
field_labels={
"learner_enrolled_count": "Total learners enrolled in school",
}
)
class Meta:
model = SchoolModel
fields = [
"school_name",
# ---
"course_name",
"course_description",
# ---
"lesson_name",
"lesson_description",
# ---
"headmaster_username",
"board_member_username"
]
рдпрд╣ рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЖрджреЗрд╢ рдирд╣реАрдВ рджреЗ рд░рд╣рд╛ рд╣реИ! рдореБрдЭреЗ рдХреЛрдИ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд╣реИ рдХреА рдХреНрдпреЛрдВред рдпрд╣ рдХрд┐рддрдиреА рдЕрдЬреАрдм рдмрд╛рдд рд╣реИред
рдЕрдЧрд░ рдореИрдВ filter
рдХреА SchoolOrderingFilter
filter
рд╡рд┐рдзрд┐ рдореЗрдВ рдбреАрдмрдЧ рдЯреНрд░реЗрд╕ рдЫреЛрдбрд╝рддрд╛ рд╣реВрдВ рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ values
None
ред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдореИрдВ рдЬреЛ рдЕрдиреБрд░реЛрдз рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ
{{API_URL}}/api/v1/schools/?offset=5&limit=3&ordering=learner_enrolled_count
рдФрд░ рдпрд╣ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рджреГрд╢реНрдп рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
class SchoolViewSet(ViewSet):
# ...
def list(self, request):
all_school_models = SchoolModel.objects.getBrowseSchoolsData()
school_filter = SchoolFilter(request.GET, queryset=all_school_models)
paginator = HeaderLinkPagination()
current_page_results = paginator.paginate_queryset(school_filter.qs,
request)
all_schools_serializer = SchoolSerializer(current_page_results,
many=True)
response_data = {
"schools": all_schools_serializer.data
}
response_to_return = paginator.get_paginated_response(response_data)
return response_to_return
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдореЗрдВ рдореЗрд░реЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ рдФрд░ рдкрд░рд┐рдХрд▓рд┐рдд рдлрд╝реАрд▓реНрдб рдСрд░реНрдбрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред
рдореИрдВ рдХреНрдпрд╛ рдЧрд▓рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ? рдХреНрдпрд╛ рдореИрдВ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЧрд▓рдд рд╕рдордЭ рд░рд╣рд╛ рд╣реВрдБ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдХрджрдо рдЙрдард╛ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреА ordering
рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣реА рд╣реИ!
рдлрд┐рд░ рд╕реЗ, рд╕рдм рдХреБрдЫ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!
рд╣рд╛рдп @loganknechtред рдореБрдЭреЗ рдХрд╣рдирд╛ рд╣реИ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдЕрджреНрднреБрдд рдореБрджреНрджреЗ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдмрд╕ рдмреЗрд╣рддрд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдмрд╕ рдЗрддрдирд╛ рд╕реНрдкрд╖реНрдЯред рдЗрд╕рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ: рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ SchoolOrderingFilter
рдХреЛ рдлрд╝реАрд▓реНрдб рдирд╛рдо o
рд╕рд╛рде рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ:
o = SchoolOrderingFilter(...)
рддреЛ рдЬрдм рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ:
рдореИрдВ рдЬреЛ рдЕрдиреБрд░реЛрдз рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ
{{API_URL}}/api/v1/schools/?offset=5&limit=3&ordering=learner_enrolled_count
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ o
рднреА рд╣реЛрдЧрд╛ред рдХреНрдпрд╛ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: {{API_URL}}/api/v1/schools/?offset=5&limit=3&o=learner_enrolled_count
?
рдлрд┐рд░ (рдореИрдВ рдЖрдкрдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдирд┐рд╢реНрдЪрд┐рдд рд╣реВрдВ) рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ it┬┤sa _computed field_ -- рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ? рдпрд╛рдиреА рдпрд╣ рдПрдХ рдРрд╕рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬреЛ рдореЙрдбрд▓ рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рдпрд╛ рдпрд╣ рдПрдХ рдкрд╛рдпрдерди рд╕рдВрдкрддреНрддрд┐ рд╣реИ?
рдкреВрдЫрдиреЗ рдХрд╛ рдПрдХ рдФрд░ рддрд░реАрдХрд╛ (рдЗрд╕рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛) рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рд╛рде рдХреНрд╡реЗрд░реАрд╕реЗрдЯ рдХрд╛рдо рдкрд░ order_by()
? рдпрд╛рдиреА рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
SchoolModel.objects.filter(...).order_by(learner_enrolled_count)
@carltongibson рдпрд╣ рдХрд╛рдлреА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ! рдореБрдЭреЗ рдЙрдореНрдореАрдж рдирд╣реАрдВ рдереА рдХрд┐ o
рдкрд░рд┐рднрд╛рд╖рд┐рдд ordering
рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛрдЧрд╛! рдореБрдЭреЗ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрдпрд╛ рдХрд┐ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рд╕реЗ ЁЯШВ
o
рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛рдХреНрдпрд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдЕрдЧрд░ рдореИрдВ рдХреНрд╡реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ
{{API_URL}}/api/v1/schools/?offset=5&limit=3&o=learner_enrolled_count
рдореБрдЭреЗ рдпреЗ рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓рддреЗ рд╣реИрдВ:
{
"schools": [
{
"id": 6,
"name": "Piano Gym Six",
"courses": [
# ...
],
"learner_enrolled_count": 0
},
{
"id": 8,
"name": "Piano Gym Eight",
"courses": [
# ...
],
"learner_enrolled_count": 0
},
{
"id": 9,
"name": "Piano Gym Nine",
"courses": [
# ...
],
"learner_enrolled_count": 0
}
]
}
рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рдореИрдВ рдЬрд┐рд╕ рдПрдХ рд╕реНрдХреВрд▓ рдХреЛ рд╢реАрд░реНрд╖ рдкрд░ рдСрд░реНрдбрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рд╡рд╣ рдЗрд╕ рдЦреЛрдЬ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдирд╣реАрдВ рд╣реИред рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрднрд╡рддрдГ рдЖрджреЗрд╢ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рд▓реЗрдХрд┐рди рдкреЗрдЬрд┐рдиреЗрд╢рди рдЕрднреА рднреА рдкрд░рд┐рдгрд╛рдо рдСрдлрд╕реЗрдЯ рдХрд░ рд░рд╣рд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЬрдм рдореИрдВрдиреЗ learner_enrolled_count
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рддреЛ рдпрд╣ рдЕрдВрддрд┐рдо рд╕реНрдерд╛рди рдкрд░ рдерд╛ред
{{API_URL}}/api/v1/schools/?limit=3&o=learner_enrolled_count
рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ -learner_enrolled_count
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ (рдСрдлрд╝рд╕реЗрдЯ рдХреЛ рд╣рдЯрд╛рдХрд░ рдФрд░ рдЕрд╡рд░реЛрд╣реА рджреНрд╡рд╛рд░рд╛ рдХреНрд░рдордмрджреНрдз рдХрд░рдирд╛)
{{API_URL}}/api/v1/schools/?limit=3&o=-learner_enrolled_count
рдФрд░ рдпрд╣ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓реА
{
"schools": [
{
"id": 7,
"name": "Piano Gym Seven",
"courses": [
# ...
],
"learner_enrolled_count": 1
},
{
"id": 1,
"name": "Piano Gym",
"courses": [
# ...
],
"learner_enrolled_count": 0
},
{
"id": 2,
"name": "Piano Gym Two",
"courses": [
# ...
],
"learner_enrolled_count": 0
}
]
}
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд┐рдпрд╛!
learner_enrolled_count
рдореЙрдбрд▓ рдкрд░ рд╣реА рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдореЗрдВ рдЗрд╕реЗ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред
рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЧреЛрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рдЬреЛрдЦрд┐рдо рдкрд░, рдпрд╣ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рд╕реНрдХреВрд▓реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдФрд░ рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рд╣реИред
рдореБрдЭреЗ рдЗрд╕ рддрд░рд╣ рдХреЗ рдореЙрдбрд▓ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
class SchoolModelManager(Manager):
def getBrowseSchoolsData(self, *args, **kwargs):
"""Return all Schools that contain lessons with flash card sets.
Does not exclude empty sets, just requires that the school has something
to enroll in
"""
# WARNING: This MUST be imported here otherwise the compilation fails
# because of circular dependencies
from piano_gym_api.versions.v1.models.flash_card_model import FlashCardModel
# from piano_gym_api.versions.v1.models.flash_card_model import PlaySheetMusicFlashCardModel
# from piano_gym_api.versions.v1.models.flash_card_model import TrueOrFalseFlashCardModel
# from piano_gym_api.versions.v1.models.flash_card_set_model import FlashCardSetModel
from piano_gym_api.versions.v1.models.sheet_music_model import SheetMusicModel
# import pdb
# pdb.set_trace()
# --------------------
sheet_music_query_set = (SheetMusicModel.objects.all()
.select_related("school"))
play_sheet_music_flash_card_sheet_music_prefetch = Prefetch("playsheetmusicflashcardmodel__sheet_music",
sheet_music_query_set)
# --------------------
flash_card_query_set = (FlashCardModel.objects.all()
.select_related("flash_card_set",
"playsheetmusicflashcardmodel",
"school",
"trueorfalseflashcardmodel")
.prefetch_related(play_sheet_music_flash_card_sheet_music_prefetch))
flash_card_prefetch = Prefetch("flash_card_set__flash_card", flash_card_query_set)
# --------------------
school_lesson_query_set = (SchoolLessonModel.objects.all()
.select_related("course",
"flash_card_set",
"school")
.prefetch_related(flash_card_prefetch))
school_lesson_prefetch = Prefetch("school_lesson", school_lesson_query_set)
# --------------------
school_course_query_set = (SchoolCourseModel.objects.all()
.select_related("school")
.prefetch_related(school_lesson_prefetch))
school_course_prefetch = Prefetch("school_course", school_course_query_set)
# --------------------
query_set_to_return = (SchoolModel.objects.filter(school_lesson__flash_card_set__isnull=False)
.distinct()
# .annotate(learner_enrolled_count=Count("learner_enrolled_school", distinct=True))
.annotate(learner_enrolled_count=Case(
When(learner_enrolled_school__learner_enrolled_course__learner_enrolled_lesson__is_enrolled=True,
then=1),
default=0,
output_field=IntegerField())
).prefetch_related(school_course_prefetch))
return query_set_to_return
calculated field
рдмрд┐рдЯ query_set_to_return
рдЪрд░ рдореЗрдВ рд╣реИред рдпрд╣ рдЬреЛ рдХрд░рддрд╛ рд╣реИ рд╡рд╣ рдХреБрд▓ рдирд╛рдорд╛рдВрдХрд┐рдд рд╢рд┐рдХреНрд╖рд╛рд░реНрдерд┐рдпреЛрдВ рдХреЗ count
рдФрд░ annotates
рдХреЛ learner_enrolled_count
ред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдпрд╣ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рд╕рд╣реА рддрд░реАрдХрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
рдПрдХ рд╕реБрдЭрд╛рд╡ рдореИрдВ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдпрд╛ рддреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдпрд╛ рд╕рд░рд▓ рдкрд╛рда рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдпреВрдЖрд░рдПрд▓ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдФрд░ рд╕рдордЭрд╛рдПрдВ рдХрд┐ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ o
рдСрд░реНрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдЬрд╛рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдм рдпрд╣ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ o
рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдХрд┐ рдСрд░реНрдбрд░рд┐рдВрдЧ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдХреНрдпрд╛ рд╕реМрдВрдкрд╛ рдЧрдпрд╛ рд╣реИ!
рдпрджрд┐ querysets
рдореИрдВ filter
рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рддреЛ рдЙрдирдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдПрдиреЛрдЯреЗрдЯ рдлрд╝реАрд▓реНрдб рд╣реИ - рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ, рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕реЗ, рдХрд┐ рдореИрдВ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдХрд╕реНрдЯрдо OrderingFilter
рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдирд╣реАрдВ рд╣реВрдВ
рддреЛ рдЙрд╕рдХреЗ рдХрд╛рд░рдг рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд╕рд╛рдзрд╛рд░рдг OrderingFilter
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ!
рдореБрдЭреЗ рд╕рд╣реА рдЬрд╡рд╛рдм рджреЛ рдЕрдЧрд░ рдореИрдВ рдЧрд▓рдд рд╣реВрдБ!
рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдпрд╣ рдореЗрд░реА рдЙрд▓рдЭрди рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ! рд╢реБрдХреНрд░рд┐рдпрд╛!
рд╣рд╛рдп @loganknechtред рд╕реБрдкрд░, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдЗрд╕реЗ рдХрд╛рдо рдХрд░ рд▓рд┐рдпрд╛ рд╣реИред рдореИрдВ
рдпрджрд┐ рдЖрдк рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЖрдк рдорд╛рдирдХ рд╡рд░реНрдЧ рд╣рд╛рдБ рдХреЗ рд╕рд╛рде рдЙрд╕ рдкрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рдФрд░ рдСрд░реНрдбрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдореИрдВ рдбреЙрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреНрд╡реАрдХ рдХрд░реВрдБрдЧрд╛ред
рдЖрдкрдХреЗ рд╕рд╣рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
@carltongibson рдФрд░ рдмрд╛рдХреА рд╕рднреА, рдЕрджреНрднреБрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рд╣рд╛рдп @loganknechtред рдореБрдЭреЗ рдХрд╣рдирд╛ рд╣реИ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдЕрджреНрднреБрдд рдореБрджреНрджреЗ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдмрд╕ рдмреЗрд╣рддрд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдмрд╕ рдЗрддрдирд╛ рд╕реНрдкрд╖реНрдЯред рдЗрд╕рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ: рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ
SchoolOrderingFilter
рдХреЛ рдлрд╝реАрд▓реНрдб рдирд╛рдоo
рд╕рд╛рде рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ:рддреЛ рдЬрдм рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ:
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░
o
рднреА рд╣реЛрдЧрд╛ред рдХреНрдпрд╛ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:{{API_URL}}/api/v1/schools/?offset=5&limit=3&o=learner_enrolled_count
?рдлрд┐рд░ (рдореИрдВ рдЖрдкрдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдирд┐рд╢реНрдЪрд┐рдд рд╣реВрдВ) рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ it┬┤sa _computed field_ -- рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ? рдпрд╛рдиреА рдпрд╣ рдПрдХ рдРрд╕рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬреЛ рдореЙрдбрд▓ рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рдпрд╛ рдпрд╣ рдПрдХ рдкрд╛рдпрдерди рд╕рдВрдкрддреНрддрд┐ рд╣реИ?
рдкреВрдЫрдиреЗ рдХрд╛ рдПрдХ рдФрд░ рддрд░реАрдХрд╛ (рдЗрд╕рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛) рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рд╛рде рдХреНрд╡реЗрд░реАрд╕реЗрдЯ рдХрд╛рдо рдкрд░
order_by()
? рдпрд╛рдиреА рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: