рдирдорд╕реНрдХрд╛рд░! рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж! рдореЗрд░реЗ рд╡рд░реНрддрдорд╛рди рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдмрд╣реБрдд рдЦреБрд╢реА рдХреА рдмрд╛рдд рд╣реИ!
рдореЗрд░реЗ рдкрд╛рд╕ рджреЛ рдореЙрдбрд▓ рд╣реИрдВ, рдПрдХ School
рдФрд░ рдПрдХ SchoolCourse
ред SchoolCourse
рдХрд╛ рдХрдИ рд╕реЗ рдПрдХ рд╕рдВрдмрдВрдз School
рдХреЗ рд╡рд┐рдкрд░реАрдд рд╣реИред
рдореИрдВ $#$ SchoolCourse
$#$ рдХреЗ name
рдХреЗ рдЖрдзрд╛рд░ рдкрд░ School
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ
рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдПрдХ рдЦрд┐рдВрдЪрд╛рд╡ рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВ рдЕрдВрддрддрдГ рднреА SchoolLesson
рджреНрд╡рд╛рд░рд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ред
class SchoolModel(Model):
name = CharField(max_length=24, unique=True)
REQUIRED_FIELDS = ["name"]
class Meta:
ordering = ("id",)
def get_courses(self):
school_courses = SchoolCourseModel.objects.filter(school=self)
return school_courses
class SchoolCourseModel(Model):
description = CharField(default="", max_length=200)
name = CharField(max_length=50)
school = ForeignKey(SchoolModel,
related_name="school_course",
on_delete=CASCADE)
REQUIRED_FIELDS = ["school", "name"]
class Meta:
ordering = ("id",)
unique_together = ("school", "name",)
def get_lessons(self):
school_lessons = SchoolLessonModel.objects.filter(course=self)
return school_lessons
рдЬреЛ - рдпрджрд┐ рдЖрдк рдбрд┐рдмрдЧ рджреГрд╢реНрдп рдореЗрдВ рдЗрди рдореЙрдбрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рддреЗ рд╣реИрдВ рддреЛ рдЖрдкрдХреЛ рдпрд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛
all_school_models[50].school_course
(Pdb++) <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x10a8177d0>
all_school_models[50].school_course.all()
(Pdb++) <QuerySet [<SchoolCourseModel: SchoolCourseModel object (151)>, <SchoolCourseModel: SchoolCourseModel object (152)>, <SchoolCourseModel: SchoolCourseModel object (153)>]>
all_school_models[50].school_course.all()[0]
(Pdb++) <SchoolCourseModel: SchoolCourseModel object (151)>
all_school_models[50].school_course.all()[0].name
(Pdb++) 'Nihongo Course One'
рдореИрдВрдиреЗ рдЬреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдмрдирд╛рдпрд╛ рд╣реИ рд╡рд╣ рдХрд╛рдлреА рд╕реАрдзрд╛-рд╕реАрдзрд╛ рд▓рдЧрддрд╛ рд╣реИред
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")
class Meta:
model = SchoolModel
fields = [
"school_name",
# ---
"course_name",
"course_description"
]
рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЕрдЧрд░ рдореИрдВ рдпрд╣ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реВрдВ:
{{API_URL}}/api/v1/schools/?course_name=Nihongo
рдореИрдВ рдЗрд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд╛рдкрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реВрдВ
{
"schools": []
}
рдореБрдЭрд╕реЗ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдЧрд▓рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ?
рдХреНрдпрд╛ рдореИрдВ django-filters рдХреА рдЧрд▓рдд рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ? рдХреНрдпрд╛ рдореИрдВ рдЧрд▓рдд рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХреЛ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдП?
рдХрд┐рд╕реА рднреА рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ!
рд╣рд╛рдп @loganknechtред рдПрдХ рд╡рд┐рд╡реЗрдХ рдЬрд╛рдВрдЪ рдХреЗ рд░реВрдк рдореЗрдВ, рдХреНрдпрд╛ рдЖрдк рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдХрд╛ URL рд╕рд╣реА рд╣реИ? рдЖрдкрдХреЗ рдЙрджрд╛рд╣рд░рдг URL рдореЗрдВ, рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ $#$ ?
$#$ рдХреЗ рдмрдЬрд╛рдп /
рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИред
рдЖрд╣ @rpkilby - рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдпрд╣ Postman
рд╕реЗ рдХреЙрдкреА рдФрд░ рдкреЗрд╕реНрдЯ рдХрд░рдиреЗ рд╕реЗ рдореЗрд░реА рдУрд░ рд╕реЗ рдПрдХ рдирд┐рд░реАрдХреНрд╖рдг рдерд╛ред рдпреВрдЖрд░рдПрд▓ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ {{API_URL}}/api/v1/schools/?offset=49&course_name=Nihongo
рд╣реИ рд▓реЗрдХрд┐рди рдореИрдВ рдХрдо рднреНрд░рдорд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП offset
рдХреЛ рд╣рдЯрд╛ рд░рд╣рд╛ рдерд╛ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдлрд▓ рд░рд╣рд╛
рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рдореЗрд░реЗ рд▓рд┐рдП рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рдореБрджреНрджрд╛ рдирд╣реАрдВ рдЙрдард╛рддрд╛ рд╣реИред рдореЗрд░рд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЕрдиреБрдорд╛рди рдпрд╣ рд╣реИ рдХрд┐ рдПрдкреАрдЖрдИ рджреГрд╢реНрдп рдореЗрдВ рдХреБрдЫ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЕрдкрдиреА рд╕реЗрдЯрд┐рдВрдЧ/рджреГрд╢реНрдп рдХреЗ filter_backends
рдореЗрдВ DjangoFilterBackend
рдЬреЛрдбрд╝рд╛ рд╣реИ? рдФрд░ рдХреНрдпрд╛ рдЖрдкрдиреЗ filterset_class = SchoolFilter
рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ filter_class
рдХрд░рддрд╛ рдерд╛)?
рдЕрд░реЗ @rpkilby
рдореЗрд░реЗ рдкрд╛рд╕ рд╡реНрдпреВ рдХреЛрдб рд╣реИ
class SchoolViewSet(ViewSet):
http_method_names = ["get", "post"]
def list(self, request):
all_school_models = SchoolModel.objects.all()
filtered_school_models = SchoolFilter(request.GET, queryset=all_school_models)
# import pdb
# pdb.set_trace()
paginator = HeaderLinkPagination()
current_page_results = paginator.paginate_queryset(filtered_school_models.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
pdb.set_trace()
рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рдореИрдВрдиреЗ рдЙрдкрд░реЛрдХреНрдд рдкреВрдЫрддрд╛рдЫ рдкреЛрд╕реНрдЯ рдХреА рдереАред
рдореИрдВрдиреЗ DjangoFilterBackend
рдХреЛ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВрдиреЗ рдорд╛рди рд▓рд┐рдпрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдерд╛ рдФрд░ рдореИрдВ рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдкрд░ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВред
рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдореИрдВрдиреЗ рдЗрд╕реЗ рдЙрд╕реА рдХрд╛рд░рдг рд╕реЗ рдХрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред
рдпрд╣ рдЬрд╛рдирдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдореИрдВ рдЗрд╕ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ SchoolModel
рдХреЗ рдирд╛рдо рдкрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдЬрдм рдореИрдВ рд░рд┐рд╡рд░реНрд╕ рдлреЙрд░реЗрди рдХреА school_course
рдкрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
рдЧреЛрдЪрд╛ - рддреЛ рдЖрдк рд╕реАрдзреЗ рджреГрд╢реНрдп рдореЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░рд╕реЗрдЯ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд╣рд╛рдБ, рдЖрдкрдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдмреИрдХрдПрдВрдб/рдлрд╝рд┐рд▓реНрдЯрд░рд╕реЗрдЯ рд╡рд░реНрдЧ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред
рдЖрдк рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдбреЗрдЯрд╛ рд╕рд╣реА рджрд┐рдЦрддрд╛ рд╣реИ, рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдереА, рдпрд╛ рдпрджрд┐ SQL рдХреНрд╡реЗрд░реА рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИред рдХреЛрд╢рд┐рд╢:
filtered_school_models = SchoolFilter(request.GET, queryset=all_school_models)
print(filtered_school_models.data)
print(filtered_school_models.errors)
print(filtered_school_models.qs)
print(str(filtered_school_models.qs.query))
@rpkilby рдпрд╣рд╛рдБ рд╡рд╣реА рд╣реИ рдЬреЛ рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдБ
<QueryDict: {'offset': ['49'], 'course_name': ['Nihongo']}>
<QuerySet [<SchoolModel: SchoolModel object (51)>]>
SELECT "piano_gym_api_schoolmodel"."id", "piano_gym_api_schoolmodel"."name", "piano_gym_api_schoolmodel"."school_board_id" FROM "piano_gym_api_schoolmodel" INNER JOIN "piano_gym_api_schoolcoursemodel" ON ("piano_gym_api_schoolmodel"."id" = "piano_gym_api_schoolcoursemodel"."school_id") WHERE UPPER("piano_gym_api_schoolcoursemodel"."name"::text) LIKE UPPER(%Nihongo%) ORDER BY "piano_gym_api_schoolmodel"."id" ASC
@rkilby рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореЗрд░реЗ рдкреЗрдЬрд┐рдиреЗрдЯрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдПрдХ рдореБрджреНрджрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ
class HeaderLinkPagination(LimitOffsetPagination):
default_limit = settings.DEFAULT_LIMIT
max_limit = settings.DEFAULT_MAX_LIMIT
min_limit = settings.DEFAULT_MIN_LIMIT
min_offset = settings.DEFAULT_MIN_OFFSET
max_offset = settings.DEFAULT_MAX_OFFSET
def get_paginated_response(self, data):
next_url = self.get_next_link()
previous_url = self.get_previous_link()
links = []
header_data = (
(previous_url, "prev"),
(next_url, "next"),
)
for url, label in header_data:
if url is not None:
links.append("<{}>; rel=\"{}\"".format(url, label))
headers = {"Link": ", ".join(links)} if links else {}
return Response(data, headers=headers)
def paginate_queryset(self, queryset, request, view=None):
limit = request.query_params.get("limit")
offset = request.query_params.get("offset")
if limit is None:
limit = settings.DEFAULT_LIMIT
if offset is None:
offset = settings.DEFAULT_OFFSET
limit = int(limit)
if limit > self.max_limit:
error_message = ("Limit should be less than or equal to {0}"
).format(self.max_limit)
errors = {"limit": [error_message]}
raise ValidationError(errors)
elif limit < self.min_limit:
error_message = ("Limit should be greater than or equal to {0}"
).format(self.min_limit)
errors = {"limit": [error_message]}
raise ValidationError(errors)
offset = int(offset)
if offset > self.max_offset:
error_message = ("Offset should be less than or equal to {0}"
).format(self.max_offset)
errors = {"offset": [error_message]}
raise ValidationError(errors)
elif offset < self.min_offset:
error_message = ("Offset should be greater than or equal to {0}"
).format(self.min_offset)
errors = {"offset": [error_message]}
raise ValidationError(errors)
import pdb
pdb.set_trace()
return super(self.__class__, self).paginate_queryset(queryset, request, view)
рдЕрдЧрд░ рдЖрдкрдХреЛ рдХреЛрдИ рд╕рдорд╛рдзрд╛рди рджрд┐рдЦрд╛рдИ рджреЗ рддреЛ рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВред рдЬрдм рддрдХ рдореИрдВ рдЗрд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ, рддрдм рддрдХ рдмрдиреЗ рд░рд╣реЗрдВред
рдореЗрд░рд╛ рдЕрдиреБрдорд╛рди рд╣реИ рдХрд┐ рдпрд╣ рджрд┐рдП рдЧрдП рдСрдлрд╕реЗрдЯ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд┐рдП рдЧрдП рдХреНрд╡реЗрд░реАрд╕реЗрдЯ рдореЗрдВ рдХреЗрд╡рд▓ 1 рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдиреБрд░реЛрдз рдкреЗрдЬрд┐рдиреЗрдЯрд░ рдХреЛ рдкрд╣рд▓реЗ 49 рдЖрдЗрдЯрдо рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣ рд░рд╣рд╛ рд╣реИред рдЕрдЧрд░ рдЖрдкрдХреЛ рдЬрд╛рдВрдЪрдирд╛ рдерд╛
print(filtered_school_models[49:])
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ <QuerySet []>
рдорд┐рд▓реЗрдЧрд╛ред
рдмрдВрдж рдХрд░рдирд╛, рдЬреИрд╕рд╛ рдХрд┐ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдкреЗрдЬрд┐рдиреЗрд╢рди рдореБрджреНрджрд╛ рд╣реИред
рдЕрд░реЗ @rpkilby
рдореИрдВ рдмрд╕ рдЗрддрдирд╛ рдХрд╣рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рдорд╛рдзреНрдпрдо рд╕реЗ рдореБрдЭрд╕реЗ рдмрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рджред рдпрд╣ рдПрдХ django-filter
рд╕рдорд╕реНрдпрд╛ рднреА рдирд╣реАрдВ рдереАред рдореИрдВ рд╕рд┐рд░реНрдл рдПрдХ рдбрд┐рдВрдЧрд╕ рдерд╛ред рдпреВ рд░рдмрд░ рдбрдХрд┐рдВрдЧ рдореА рд╕реБрдкрд░ рд╕реБрдкрд░ рд╕рд░рд╛рд╣реЗ рдЧрдП рд╣реИрдВред
рдЖрдк рдЕрджреНрднреБрдд рд╣реИрдВ, рдФрд░ рдПрдХ рдмрд╛рд░ рдлрд┐рд░, рдЗрд╕ рдЕрджреНрднреБрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!
рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВред рдорджрдж рдХрд░рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреА!
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдореЗрд░рд╛ рдЕрдиреБрдорд╛рди рд╣реИ рдХрд┐ рдпрд╣ рджрд┐рдП рдЧрдП рдСрдлрд╕реЗрдЯ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд┐рдП рдЧрдП рдХреНрд╡реЗрд░реАрд╕реЗрдЯ рдореЗрдВ рдХреЗрд╡рд▓ 1 рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдиреБрд░реЛрдз рдкреЗрдЬрд┐рдиреЗрдЯрд░ рдХреЛ рдкрд╣рд▓реЗ 49 рдЖрдЗрдЯрдо рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣ рд░рд╣рд╛ рд╣реИред рдЕрдЧрд░ рдЖрдкрдХреЛ рдЬрд╛рдВрдЪрдирд╛ рдерд╛
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ
<QuerySet []>
рдорд┐рд▓реЗрдЧрд╛редрдмрдВрдж рдХрд░рдирд╛, рдЬреИрд╕рд╛ рдХрд┐ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдкреЗрдЬрд┐рдиреЗрд╢рди рдореБрджреНрджрд╛ рд╣реИред