{"id":393774,"date":"2024-06-29T11:12:54","date_gmt":"2024-06-29T11:12:54","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=393774"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=393774","title":{"rendered":"<span>\u041a\u0430\u043a \u0441\u0442\u0430\u0436\u0451\u0440 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043d\u0430\u0448\u0435\u043b \u0431\u0430\u0433 \u0432 Django<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/fd6\/bda\/9e9\/fd6bda9e957347ddbacb81b2efd5cb8b.jpg\" width=\"2000\" height=\"1141\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fd6\/bda\/9e9\/fd6bda9e957347ddbacb81b2efd5cb8b.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0418\u0432\u0430\u043d, \u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a-\u0441\u0442\u0430\u0436\u0451\u0440 \u0432 <a href=\"https:\/\/kts.studio\/\"><u>KTS<\/u><\/a>.\u00a0<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0448\u0435\u043b \u0431\u0430\u0433 \u0432 Django, \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0438\u043a\u0435\u0442 \u0441 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438 \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u043b\u0438.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u2014 \u043d\u0430\u0434 \u0447\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u0432 \u0447\u0451\u043c \u0431\u044b\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0435\u0451 \u0441\u043b\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0435\u0449\u0451 \u043f\u0440\u043e \u043e\u0434\u0438\u043d \u0431\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0444\u0438\u0447\u0435\u0439 ?.<\/p>\n<p>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435:<\/p>\n<ul>\n<li>\n<p><a href=\"#1\">\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0440\u0430\u0431\u043e\u0442\u0435 Django<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#2\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#3\">\u041e\u0448\u0438\u0431\u043a\u0430 Django<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#4\">\u041f\u0440\u0438\u0447\u0438\u043d\u044b \u0431\u0430\u0433\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#5\">\u0422\u0438\u043a\u0435\u0442 \u0438 Pull Request<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#6\">\u041d\u0430\u0448\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#7\">\u0411\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0444\u0438\u0447\u0435\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#8\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0441\u0435\u0431\u0435: \u043a\u0430\u043a \u0441\u043c\u0435\u043d\u0438\u043b \u0440\u043e\u0434 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043f\u0430\u043b \u043d\u0430 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0443 \u0432 KTS.<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/322\/75e\/80c\/32275e80c867596d94331fb123eb81cd.png\" alt=\"\" title=\"\" width=\"502\" height=\"501\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/322\/75e\/80c\/32275e80c867596d94331fb123eb81cd.png\"\/><\/figure>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0432\u044b\u0441\u0448\u0435\u0435 \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0441\u043a\u043e\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 4 \u0433\u043e\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0445\u0438\u0440\u0443\u0440\u0433\u043e\u043c.\u00a0<\/p>\n<p>\u0421\u043e \u0448\u043a\u043e\u043b\u044b \u043c\u0435\u043d\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u043d\u043e \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0434\u043e\u043b\u0433\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0441\u044f \u043b\u0438\u0448\u044c \u0432 \u0432\u0438\u0434\u0435 \u0445\u043e\u0431\u0431\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0434\u0435\u043b\u0430\u043b \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0430\u0442\u0447\u0438 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b. \u041d\u0430 \u0443\u0440\u043e\u043a\u0430\u0445 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u043a\u0438 \u043f\u0440\u0435\u043f\u043e\u0434\u0430\u0432\u0430\u043b\u0438 \u043b\u0438\u0448\u044c Word \u0438 PowerPoint, \u0430 \u043a\u0440\u0435\u043f\u043a\u043e\u0439 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0431\u0430\u0437\u044b \u0438\u043b\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0445, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 IT, \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e. \u0422\u0430\u043a \u0447\u0442\u043e \u044f \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b IT \u043a\u0430\u043a \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044e.\u00a0<\/p>\n<p>\u0412 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u044f \u0447\u0438\u0442\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0440\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438 \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0437\u0433\u0430. \u041d\u0430 4-\u043c \u043a\u0443\u0440\u0441\u0435 \u043c\u0435\u0434\u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0438 \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0441\u043e\u0437\u0440\u0435\u043b \u0434\u043b\u044f \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u0434\u0430\u0432\u043d\u043e \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u043b Python, \u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043d\u0438\u0433\u0435 \u041c\u0430\u0440\u043a\u0430 \u041b\u0443\u0442\u0446\u0430 \u00ab\u0418\u0437\u0443\u0447\u0430\u0435\u043c Python\u00bb \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u043c\u043e\u0451 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u043c\u0438\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043a\u0430\u0439\u0444, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043e\u0449\u0443\u0442\u0438\u043b \u043e\u0442 \u043f\u0435\u0440\u0432\u044b\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430! \u0422\u0430\u043a \u0438\u0437 \u0433\u043e\u0434\u0430 \u0432 \u0433\u043e\u0434, \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e, \u043d\u043e \u0432\u0435\u0440\u043d\u043e, \u043f\u043e\u0432\u044b\u0448\u0430\u043b\u0438\u0441\u044c \u043c\u043e\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u043f\u043e Python. \u0415\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0433\u0440\u0430\u043b\u0441\u044f \u0441 Unity.<\/p>\n<p>\u042f \u043b\u044e\u0431\u043b\u044e \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0443, \u043d\u043e \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u0435\u043d\u044f \u043d\u0435 \u043f\u043e\u043a\u0438\u0434\u0430\u043b\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u2014 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0445\u0438\u0440\u0443\u0440\u0433\u0430 \u044f \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0440\u0435\u0448\u0438\u043b\u0441\u044f \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u043e\u0434 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043b\u043e\u0442\u043d\u043e \u0437\u0430\u043d\u044f\u043b\u0441\u044f \u0441\u0430\u043c\u043e\u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\u043c. \u041d\u0430\u0447\u0430\u043b \u0441\u043e \u0448\u043a\u043e\u043b\u044c\u043d\u044b\u0445 \u043a\u0443\u0440\u0441\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0442\u043e\u043c \u0438\u0437\u0443\u0447\u0430\u043b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438 \u0440\u0435\u0448\u0430\u043b \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043a \u0448\u043a\u043e\u043b\u044c\u043d\u044b\u043c \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u0430\u043c, \u0447\u0438\u0442\u0430\u043b \u043e \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435.<\/p>\n<p>\u0412 \u044f\u043d\u0432\u0430\u0440\u0435 2022 \u0433\u043e\u0434\u0430 \u043f\u043e \u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0441\u0442\u0438 \u0443\u0437\u043d\u0430\u043b \u043e \u043d\u0430\u0431\u043e\u0440\u0435 \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0443\u044e \u0448\u043a\u043e\u043b\u0443 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u043d\u0430\u0431\u043e\u0440\u0430 \u0443\u0441\u043f\u0435\u043b \u043f\u043e\u0434\u0430\u0442\u044c \u0437\u0430\u044f\u0432\u043a\u0443. \u0417\u0430 \u043c\u0435\u0441\u044f\u0446 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0441\u044f \u0441 aiohttp, \u043e\u0442\u043a\u0440\u044b\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u043c\u043e\u0449\u044c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445, SQL \u0438 ORM. \u0421\u0442\u0430\u043b\u043e \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0449\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u041c\u0435\u0441\u0442\u0430\u043c\u0438 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0442\u0440\u0443\u0434\u043d\u043e \u0438 \u0431\u043e\u043b\u044c\u043d\u043e, \u043d\u043e \u043e\u043d\u043e \u0442\u043e\u0433\u043e \u0441\u0442\u043e\u0438\u043b\u043e. \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438\u0437\u0443\u0447\u0438\u043b \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 git.\u00a0<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u043c\u0435\u043d\u044f \u043f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u043b\u0438 \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u043d\u0430 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0443.\u00a0<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0441\u043b\u0443\u0447\u0430\u0435\u043c, \u0445\u043e\u0447\u0443 \u043f\u043e\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u0442\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0438 \u043d\u0430\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043a\u043e\u043b\u043b\u0435\u0433 \u0438\u0437 KTS, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441\u0432\u043e\u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0430\u0432\u043d\u0438\u043a\u0430 \u0421\u0430\u0448\u0443 ?.<\/p>\n<\/div>\n<\/details>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0440\u0430\u0431\u043e\u0442\u0435 Django<\/h2>\n<p>\u0417\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 Django \u044f \u043d\u0430\u0447\u0430\u043b \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0441 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u043d\u0435\u0439 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0438. \u0420\u0430\u043d\u0435\u0435 \u0431\u044b\u043b \u043e\u043f\u044b\u0442 \u0441 aiohttp + SQLAlchemy\/GINO.\u00a0<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u0442\u044b\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 <a href=\"https:\/\/www.djangoproject.com\/\"><u>Django<\/u><\/a> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Django <a href=\"https:\/\/ru.wikipedia.org\/wiki\/ORM\"><u>ORM<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Python-\u043a\u043e\u0434\u0430 \u0432 \u044f\u0437\u044b\u043a SQL. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u00ab\u043d\u043e\u00bb. \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 N+1 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0435, \u0442\u0435\u043c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 Django \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#select-related\"><u>select_related<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#prefetch-related\"><u>prefetch_related<\/u> <\/a>(\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#prefetch-objects\"><u>Prefetch<\/u><\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#only\"><u>only<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f API \u0438\u043c\u0435\u0435\u0442\u0441\u044f 2 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: <a href=\"https:\/\/habr.com\/ru\/post\/335158\/\"><u>REST API \u0438 GraphQL<\/u><\/a>. \u0412 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/graphql.org\/\"><u>GraphQL<\/u><\/a>.\u00a0<\/p>\n<p>REST API \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0440\u043e\u0433\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0411\u0414 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e (\u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c). GraphQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u043a\u043b\u0438\u0435\u043d\u0442 \u0441\u0430\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e. \u041c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u043b\u0430\u0442\u044c select_related \u0438 prefetch_related \u043f\u043e \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044f\u043c, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0441\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0431\u0443\u0434\u0443\u0442 \u043b\u0438\u0448\u043d\u0438\u0435 \u00ab\u0434\u0436\u043e\u0439\u043d\u044b\u00bb \u0438 \u0438\u0437 \u0411\u0414 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/h2>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u0437\u044f\u043b\u0441\u044f \u0437\u0430 \u0435\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0418\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 info (\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0435), \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043a\u043b\u044e\u0447\u0430\u043c \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0435 <code>_meta<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u0430, \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/docs.python.org\/3\/library\/functools.html\"><u>functools<\/u><\/a>.<\/p>\n<p>\u0412 <code>info<\/code> \u0432\u0441\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 CamelCase, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0438\u0445 \u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0443 <code>snake_case<\/code>. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/docs.python.org\/3\/library\/re.html\"><u>\u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/u><\/a>. \u0412 \u0438\u0442\u043e\u0433\u0435 <code>waitingAsyncDjango<\/code> \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <code>waiting_async_django<\/code>:<\/p>\n<pre><code class=\"python\">camel_case_pattern = re.compile(r\"(?&lt;!^)(?=[A-Z])\")  def string_to_snake_case(value: str) -> str: return camel_case_pattern.sub(\"_\", value).lower()<\/code><\/pre>\n<p>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0443\u0437\u043d\u0430\u0451\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u044f \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 GraphQL. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c <code>ast_to_dict<\/code>, \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0435\u0440\u0451\u043c \u0438\u0437 info:<\/p>\n<pre><code class=\"python\">from graphql.utils.ast_to_dict import ast_to_dict  def collect_gql_fields( node: dict, fragments: dict, snake_case: bool = True, ) -> dict[str, dict]: field = {} if node.get(\"selection_set\"): for leaf in node[\"selection_set\"][\"selections\"]: if leaf[\"kind\"] == \"Field\": key = leaf[\"name\"][\"value\"] if snake_case: key = string_to_snake_case(key) field.update({key: collect_gql_fields(leaf, fragments)}) elif leaf[\"kind\"] == \"FragmentSpread\": field.update( collect_gql_fields(fragments[leaf[\"name\"][\"value\"]], fragments) ) return field  def get_gql_fields( info: ResolveInfo, snake_case: bool = True, ) -> dict[str, dict]: fragments = {} node = ast_to_dict(info.field_asts[0]) for name, value in info.fragments.items(): fragments[name] = ast_to_dict(value) return collect_gql_fields(node, fragments, snake_case=snake_case)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>only<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_all_field_names(model: Type[models.Model]) -> list[str]: return [field.name for field in model._meta.fields]<\/code><\/pre>\n<p>\u0414\u043b\u044f <code>select_related<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 <em>many-to-one<\/em> \u0438 <em>one-to-one<\/em>, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u044d\u0442\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_fields_to_select( model: Type[models.Model], ) -> dict[str, Type[models.Model]]: fields = { field.name: field.related_model for field in model._meta.fields if field.many_to_one or field.one_to_one } related_fields = { field.name: field.related_model for field in model._meta.fields_map.values() if field.many_to_one or field.one_to_one } return fields | related_fields<\/code><\/pre>\n<p>\u0414\u043b\u044f <code>prefetch_related<\/code> \u0438 <code>Prefetch<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 <em>one-to-many <\/em>\u0438<em> many-to-many<\/em>, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u044d\u0442\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_fields_to_prefetch( model: Type[models.Model], ) -> dict[str, Type[models.Model]]: one_to_many = { field.name: field.related_model for field in model._meta.fields if field.one_to_many or field.many_to_many } many_to_many = { field.name: field.related_model  for field in model._meta.many_to_many } related_fields = { field.name: field.related_model for field in model._meta.fields_map.values() if field.one_to_many or field.many_to_many } return one_to_many | many_to_many | related_fields<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <em>dataclass<\/em>:<\/p>\n<pre><code class=\"python\">@dataclass class ModelFields: select_fields: list[str] prefetch_fields: list[str | Prefetch] only_fields: list[str]<\/code><\/pre>\n<p>\u0423\u0437\u043d\u0430\u0432 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u0442\u0438\u043f\u044b \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">def collect_model_fields( model: Type[models.Model], gql_fields: dict, prefix: str = \"\", ) -> ModelFields: all_field_names = _get_model_all_field_names(model) to_select = _get_model_fields_to_select(model) to_prefetch = _get_model_fields_to_prefetch(model)  select_fields, prefetch_fields, only_fields = [], [], []  # \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043f\u043e\u043b\u044f\u043c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 for field_name in gql_fields.keys(): # \u0447\u0435\u043c \u0433\u043b\u0443\u0431\u0436\u0435 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0442\u0435\u043c \u0434\u043b\u0438\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 location = prefix + field_name next_prefix = location + \"__\"      if field_name in to_select: # \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 - \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f many-to-one \u0438\u043b\u0438 one-to-one  # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 next_fields = collect_model_fields( to_select[field_name], gql_fields[field_name], prefix=next_prefix, )        # \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043a \u0443\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c if next_fields.only_fields: # \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u043b\u0430\u0442\u044c select_related # \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0438\u0437 \u043d\u0435\u0435 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0434\u043b\u044f .only(), # \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0422\u041e\u041b\u042c\u041a\u041e \u0434\u043b\u044f prefetch, # \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. select_fields.append(location) only_fields.extend(next_fields.only_fields)          select_fields.extend(next_fields.select_fields) prefetch_fields.extend(next_fields.prefetch_fields)        elif field_name in to_prefetch: # \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 - \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f one-to-many \u0438\u043b\u0438 many-to-many # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 next_fields = collect_model_fields( to_prefetch[field_name], gql_fields[field_name], prefix=next_prefix, )        # \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043a \u0443\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c prefetch_fields.extend(next_fields.prefetch_fields) if next_fields.select_fields: # \u0435\u0441\u043b\u0438 \u0443 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u043f\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 # \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f many-to-one \u0438\u043b\u0438 one-to-one, # \u0442\u043e \u0434\u043b\u044f \u0431\u041e\u043b\u044c\u0448\u0435\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 Prefetch related_select_fields = [ i.removeprefix(next_prefix) for i in next_fields.select_fields ] queryset = to_prefetch[field_name].objects.select_related( *related_select_fields ) prefetch_fields.append(Prefetch(location, queryset=queryset)) else: prefetch_fields.append(location)        elif field_name in all_field_names: # \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 only_fields.append(location)        else: # property \u0438 \u043f\u0440\u043e\u0447\u0435\u0435. pass  return ModelFields( select_fields=select_fields, prefetch_fields=prefetch_fields, only_fields=only_fields, )   def get_optimization_fields( model: Type[models.Model], info: ResolveInfo, ) -> ModelFields: # \u0443\u0437\u043d\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f gql_fields = get_gql_fields(info, snake_case=True)  # \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 return collect_model_fields(model, gql_fields) <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0435\u0439:<\/p>\n<pre><code class=\"python\">class OptimizedModelManager(models.Manager): def db_prepared(self, info: ResolveInfo) -> models.QuerySet: fields = get_optimization_fields(self.model, info) return ( self.get_queryset() .select_related(*fields.select_fields) .prefetch_related(*fields.prefetch_fields) .only(*fields.only_fields) )   class OptimizedModel(models.Model): class Meta: abstract = True  objects = OptimizedModelManager() <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u0438 \u043b\u044e\u0431\u044b\u0435 GraphQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b:<\/p>\n<pre><code class=\"python\"># \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u0441\u044f \u043e\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 class Book(OptimizedModel): \"\"\"\u041e\u0431\u044b\u0447\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043a\u043d\u0438\u0433\u0438.\"\"\"  class BookGQLType(DjangoObjectType): class Meta: model = Book  class Queries(ObjectType): books = List(NonNull(BookGQLType), required=True)  def resolve_books(self, info: ResolveInfo) -> list[Book]: # \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d return Book.objects.db_prepared(info)<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043e\u0431\u0440\u043e\u0441 \u043d\u043e\u0432\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 property \u043c\u043e\u0434\u0435\u043b\u0435\u0439.<\/p>\n<p><a class=\"anchor\" name=\"3\" id=\"3\"><\/a><\/p>\n<h2>\u041e\u0448\u0438\u0431\u043a\u0430 Django<\/h2>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>only<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u043b\u0443\u0447\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u043e\u043b\u044f, \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 <code>only<\/code> \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0436\u043e\u0439\u043d\u0435\u043d\u044b.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e<\/strong> \u0442\u043e, \u0447\u0442\u043e Django \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0441\u0442\u0430\u0435\u0442 pk (primary key) \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 <code>only<\/code>.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 Django \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u0438\u0445 \u0436\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u0411\u0414 \u0431\u0443\u0434\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c. \u042d\u0442\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u0447\u0435\u0442 <a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/topics\/db\/models\/#proxy-models\"><u>proxy-\u043c\u043e\u0434\u0435\u043b\u0435\u0439<\/u><\/a>.<\/p>\n<p>\u0418 \u0432\u043e\u0442 \u043f\u0440\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a proxy-\u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u0442\u0430\u043a\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430:<\/p>\n<pre><code class=\"python\">File \"django\\db\\models\\query.py\", line 302, in len self._fetch_all() File \"django\\db\\models\\query.py\", line 1507, in _fetch_all self._result_cache = list(self._iterable_class(self)) File \"django\\db\\models\\query.py\", line 71, in iter related_populators = get_related_populators(klass_info, select, db) File \"django\\db\\models\\query.py\", line 2268, in get_related_populators rel_cls = RelatedPopulator(rel_klass_info, select, db) File \"django\\db\\models\\query.py\", line 2243, in init self.pk_idx = self.init_list.index(self.model_cls._meta.pk.attname) ValueError: 'id' is not in list<\/code><\/pre>\n<p>\u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e, \u0447\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c proxy-\u043c\u043e\u0434\u0435\u043b\u044c \u0432 <code>select_related<\/code> \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c <code>only<\/code>. \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 <code>only<\/code>.<\/p>\n<p><a class=\"anchor\" name=\"4\" id=\"4\"><\/a><\/p>\n<h2>\u041f\u0440\u0438\u0447\u0438\u043d\u044b \u0431\u0430\u0433\u0430<\/h2>\n<p>\u0421\u0443\u0434\u044f \u043f\u043e \u0432\u0441\u0435\u043c\u0443, \u0443 \u043f\u0440\u043e\u043a\u0441\u0438-\u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0441\u044f pk, \u0445\u043e\u0442\u044f \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.\u00a0<\/p>\n<p>\u042f \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b pk (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e id) proxy-\u043c\u043e\u0434\u0435\u043b\u0438 \u0432 <code>only<\/code>, \u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u0441\u0447\u0435\u0437\u043b\u0430. \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0433\u0434\u0435-\u0442\u043e \u0432 Django.<\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b \u0438\u0441\u043a\u0430\u0442\u044c, \u0433\u0434\u0435 Django \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 pk \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0435\u0439. \u041f\u043e\u0438\u0441\u043a\u0438 \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u0432 <code>django\/db\/models\/sql\/query.py<\/code>, \u043a\u043b\u0430\u0441\u0441 <code>Query<\/code>, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>deffered_to_data<\/code>.\u00a0<\/p>\n<p>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u0435\u0431\u0430\u0433\u0430 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b, \u0447\u0442\u043e pk \u0434\u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0443 \u043f\u0440\u043e\u043a\u0441\u0438-\u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u2014 \u0443 \u0431\u0430\u0437\u043e\u0432\u043e\u0439.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043f\u043e\u0434\u043e\u0437\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c:<\/p>\n<pre><code class=\"python\">opts = cur_model._meta if not is_reverse_o2o(source): must_include[old_model].add(source) add_to_dict(must_include, cur_model, opts.pk)<\/code><\/pre>\n<p>\u041e\u0448\u0438\u0431\u043a\u0430 \u0438\u0441\u0447\u0435\u0437\u043b\u0430, \u043a\u043e\u0433\u0434\u0430 pk \u0441\u0442\u0430\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0443 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438:\u00a0<\/p>\n<pre><code class=\"python\">opts = cur_model._meta.concrete_model._meta if not is_reverse_o2o(source): must_include[old_model].add(source) add_to_dict(must_include, cur_model, opts.pk)<\/code><\/pre>\n<p><a class=\"anchor\" name=\"5\" id=\"5\"><\/a><\/p>\n<h2>\u0422\u0438\u043a\u0435\u0442 \u0438 Pull Request<\/h2>\n<p>\u0423\u0431\u0435\u0434\u0438\u0432\u0448\u0438\u0441\u044c, \u0447\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Django Issues \u043d\u0435 \u0431\u044b\u043b\u043e \u0442\u0438\u043a\u0435\u0442\u043e\u0432 \u0441 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u0431\u0430\u0433\u043e\u043c, \u044f \u0441\u043e\u0437\u0434\u0430\u043b <a href=\"https:\/\/code.djangoproject.com\/ticket\/33816\"><u>\u043d\u043e\u0432\u044b\u0439<\/u><\/a>. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0435\u0433\u043e \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u0442\u0447. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c pull request \u0441 \u0444\u0438\u043a\u0441\u043e\u043c \u0431\u0430\u0433\u0430 \u0438 \u0442\u0435\u0441\u0442\u043e\u043c. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0432 Django \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.djangoproject.com\/en\/dev\/intro\/contributing\/\"><u>\u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f.<\/u><\/a><\/p>\n<p>\u0422\u0430\u043a \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 <a href=\"https:\/\/github.com\/django\/django\/commit\/425718726b7d2edd7b8a043f8976e437262b5098\"><u>pull request<\/u><\/a> \u0432 open-source \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/a2b\/f28\/490\/a2bf28490fb7f7e4bb82856fbdb1ec19.jpeg\" width=\"600\" height=\"400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a2b\/f28\/490\/a2bf28490fb7f7e4bb82856fbdb1ec19.jpeg\" data-blurred=\"true\"\/><\/figure>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0442 \u0431\u0430\u0433 \u0442\u043e\u0436\u0435 \u043f\u043e\u0444\u0438\u043a\u0441\u0438\u043b\u0438: \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 pk \u0432 only \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u0435\u0439 proxy-\u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p><a class=\"anchor\" name=\"6\" id=\"6\"><\/a><\/p>\n<h2>\u041d\u0430\u0448\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0447\u0442\u043e \u043c\u044b \u0432\u0440\u044f\u0434 \u043b\u0438 \u043d\u0430\u0448\u043b\u0438 \u0431\u044b \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443 \u0431\u0435\u0437 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041c\u044b \u0438\u0441\u043a\u0430\u043b\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0438 \u0434\u0430\u0436\u0435 \u043d\u0430\u0448\u043b\u0438 \u043e\u0434\u043d\u0443 \u2014 <a href=\"https:\/\/github.com\/tfoxy\/graphene-django-optimizer\"><u>https:\/\/github.com\/tfoxy\/graphene-django-optimizer<\/u><\/a>. \u041d\u043e \u043e\u043d\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0433\u0438\u0431\u043a\u043e\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445 \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u0430\u043b\u0430 \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414, \u0447\u0435\u043c \u043d\u0430\u0448\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<p>\u0411\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0433\u043e \u043c\u044b \u043d\u0435 \u043d\u0430\u0448\u043b\u0438, \u043d\u043e \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0435\u0442\u0435, \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 ?<\/p>\n<p><a class=\"anchor\" name=\"7\" id=\"7\"><\/a><\/p>\n<h2>\u0411\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0444\u0438\u0447\u0435\u0439<\/h2>\n<p>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u043d\u0430\u0448\u0435\u043b \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0431\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414. \u041e\u043d \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c Prefetch \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u043e\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435.<\/p>\n<pre><code class=\"python\">class Author(models.Model): name = models.CharField(max_length=32)  class Book(models.Model): title = models.CharField(max_length=32) author = models.ForeignKey(\"Author\", on_delete=models.CASCADE)  # \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 Publisher \u044d\u0442\u043e \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 publisher = models.ForeignKey( \"Publisher\", on_delete=models.CASCADE, related_name=\"books\", )  class Publisher(models.Model): address = models.CharField(max_length=32)<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c GraphQL \u0437\u0430\u043f\u0440\u043e\u0441\u0435\u2026<\/p>\n<pre><code class=\"python\">{ publishers { address books { title author { name } } } }<\/code><\/pre>\n<p>\u2026 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439:<\/p>\n<pre><code class=\"python\">def resolve_publishers(self, info: ResolveInfo) -> list[Publisher]: queryset = Book.objects.select_related(\"author\").only(\"title\", \"author__name\") return Publisher.objects.prefetch_related(Prefetch(\"books\", queryset)).only(\"address\")<\/code><\/pre>\n<p>\u041d\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414.<\/p>\n<p>\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435:<\/p>\n<pre><code class=\"python\">Book.objects.select_related(\"author\").only(\"title\", \"author__name\")<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 only \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0439 pk (publisher_id), \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432 10 \u0440\u0430\u0437 \u043c\u0435\u043d\u044c\u0448\u0435 (\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0411\u0414):<\/p>\n<pre><code class=\"python\">Book.objects.select_related(\"author\").only(\"title\", \"author__name\", \"publisher_id\")<\/code><\/pre>\n<p>\u041d\u0430\u0439\u0434\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0431\u0430\u0433\u0430 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u0435\u0433\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0435\u0449\u0435 \u043e\u0434\u0438\u043d <a href=\"https:\/\/code.djangoproject.com\/ticket\/33835\"><u>\u0442\u0438\u043a\u0435\u0442<\/u><\/a>.\u00a0\u041d\u043e&#8230;<\/p>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bce\/e7c\/5ff\/bcee7c5ffffda21164b7e8a6a6a43c7d.png\" width=\"597\" height=\"401\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bce\/e7c\/5ff\/bcee7c5ffffda21164b7e8a6a6a43c7d.png\"\/><\/figure>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>prefetch_related_objects<\/code> \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043d\u0435\u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u043c \u0438 \u0432\u0432\u043e\u0434\u044f\u0449\u0438\u043c \u0432 \u0437\u0430\u0431\u043b\u0443\u0436\u0434\u0435\u043d\u0438\u0435. \u041e\u043d\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438, \u0447\u0442\u043e \u0442\u0435, \u043a\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>only<\/code> \u0438 <code>defer<\/code>, \u043d\u0435\u0441\u0443\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432 \u043d\u0438\u0445 \u043f\u043e\u043b\u044f.\u00a0<\/p>\n<p>\u0422\u0438\u043a\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u043b\u0435\u0436\u0430\u043b \u0444\u0438\u043a\u0441\u0443 \u0438 \u0431\u044b\u043b \u043e\u0442\u043c\u0435\u0447\u0435\u043d \u043a\u0430\u043a <em>New feature<\/em>.<\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0431\u0440\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>only<\/code> \u0432 Prefetch.<\/p>\n<p><a class=\"anchor\" name=\"8\" id=\"8\"><\/a><\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<details class=\"spoiler\">\n<summary>PS \u2014 Django 4.1<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/448\/192\/0d2\/4481920d21c57386432c498b84efe5df.png\" width=\"595\" height=\"624\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/448\/192\/0d2\/4481920d21c57386432c498b84efe5df.png\"\/><\/figure>\n<p>\u0412 \u0430\u0432\u0433\u0443\u0441\u0442\u0435 2022 \u0433\u043e\u0434\u0430 \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u043b\u0438\u0437 <a href=\"https:\/\/docs.djangoproject.com\/en\/dev\/releases\/4.1\/\"><u>Django 4.1<\/u><\/a>, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f Django ORM. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435, \u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0434 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u0438. \u0414\u0443\u043c\u0430\u044e, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442, \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0432\u044b\u0431\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c.\u00a0<\/p>\n<\/div>\n<\/details>\n<p>?? 8 \u0430\u0432\u0433\u0443\u0441\u0442\u0430 \u2014 \u0441\u0442\u0430\u0440\u0442 \u043d\u0430\u0448\u0435\u0439 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u0448\u043a\u043e\u043b\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 <a href=\"https:\/\/metaclass.kts.studio\/beginner_react?utm_source=habr\"><u>\u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u043e\u0432<\/u><\/a> \u0438 <a href=\"https:\/\/metaclass.kts.studio\/beginner_backend?utm_source=habr\"><u>\u0431\u044d\u043a\u0435\u043d\u0434\u0435\u0440\u043e\u0432<\/u><\/a>.\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0448\u0442\u0443\u043a\u0438, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0435!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/680572\/\"> https:\/\/habr.com\/ru\/articles\/680572\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0418\u0432\u0430\u043d, \u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a-\u0441\u0442\u0430\u0436\u0451\u0440 \u0432 <a href=\"https:\/\/kts.studio\/\"><u>KTS<\/u><\/a>.\u00a0<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0448\u0435\u043b \u0431\u0430\u0433 \u0432 Django, \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0438\u043a\u0435\u0442 \u0441 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438 \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u043b\u0438.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u2014 \u043d\u0430\u0434 \u0447\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u0432 \u0447\u0451\u043c \u0431\u044b\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0435\u0451 \u0441\u043b\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0435\u0449\u0451 \u043f\u0440\u043e \u043e\u0434\u0438\u043d \u0431\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0444\u0438\u0447\u0435\u0439 ?.<\/p>\n<p>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435:<\/p>\n<ul>\n<li>\n<p><a href=\"#1\">\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0440\u0430\u0431\u043e\u0442\u0435 Django<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#2\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#3\">\u041e\u0448\u0438\u0431\u043a\u0430 Django<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#4\">\u041f\u0440\u0438\u0447\u0438\u043d\u044b \u0431\u0430\u0433\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#5\">\u0422\u0438\u043a\u0435\u0442 \u0438 Pull Request<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#6\">\u041d\u0430\u0448\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#7\">\u0411\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0444\u0438\u0447\u0435\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#8\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0441\u0435\u0431\u0435: \u043a\u0430\u043a \u0441\u043c\u0435\u043d\u0438\u043b \u0440\u043e\u0434 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043f\u0430\u043b \u043d\u0430 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0443 \u0432 KTS.<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><\/figure>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0432\u044b\u0441\u0448\u0435\u0435 \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0441\u043a\u043e\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 4 \u0433\u043e\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0445\u0438\u0440\u0443\u0440\u0433\u043e\u043c.\u00a0<\/p>\n<p>\u0421\u043e \u0448\u043a\u043e\u043b\u044b \u043c\u0435\u043d\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u043d\u043e \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0434\u043e\u043b\u0433\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0441\u044f \u043b\u0438\u0448\u044c \u0432 \u0432\u0438\u0434\u0435 \u0445\u043e\u0431\u0431\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0434\u0435\u043b\u0430\u043b \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0430\u0442\u0447\u0438 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b. \u041d\u0430 \u0443\u0440\u043e\u043a\u0430\u0445 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u043a\u0438 \u043f\u0440\u0435\u043f\u043e\u0434\u0430\u0432\u0430\u043b\u0438 \u043b\u0438\u0448\u044c Word \u0438 PowerPoint, \u0430 \u043a\u0440\u0435\u043f\u043a\u043e\u0439 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0431\u0430\u0437\u044b \u0438\u043b\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0445, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 IT, \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e. \u0422\u0430\u043a \u0447\u0442\u043e \u044f \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b IT \u043a\u0430\u043a \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044e.\u00a0<\/p>\n<p>\u0412 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u044f \u0447\u0438\u0442\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0440\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438 \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0437\u0433\u0430. \u041d\u0430 4-\u043c \u043a\u0443\u0440\u0441\u0435 \u043c\u0435\u0434\u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0438 \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0441\u043e\u0437\u0440\u0435\u043b \u0434\u043b\u044f \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u0434\u0430\u0432\u043d\u043e \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u043b Python, \u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043d\u0438\u0433\u0435 \u041c\u0430\u0440\u043a\u0430 \u041b\u0443\u0442\u0446\u0430 \u00ab\u0418\u0437\u0443\u0447\u0430\u0435\u043c Python\u00bb \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u043c\u043e\u0451 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u043c\u0438\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043a\u0430\u0439\u0444, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043e\u0449\u0443\u0442\u0438\u043b \u043e\u0442 \u043f\u0435\u0440\u0432\u044b\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430! \u0422\u0430\u043a \u0438\u0437 \u0433\u043e\u0434\u0430 \u0432 \u0433\u043e\u0434, \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e, \u043d\u043e \u0432\u0435\u0440\u043d\u043e, \u043f\u043e\u0432\u044b\u0448\u0430\u043b\u0438\u0441\u044c \u043c\u043e\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u043f\u043e Python. \u0415\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0433\u0440\u0430\u043b\u0441\u044f \u0441 Unity.<\/p>\n<p>\u042f \u043b\u044e\u0431\u043b\u044e \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0443, \u043d\u043e \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u0435\u043d\u044f \u043d\u0435 \u043f\u043e\u043a\u0438\u0434\u0430\u043b\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u2014 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0445\u0438\u0440\u0443\u0440\u0433\u0430 \u044f \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0440\u0435\u0448\u0438\u043b\u0441\u044f \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u043e\u0434 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043b\u043e\u0442\u043d\u043e \u0437\u0430\u043d\u044f\u043b\u0441\u044f \u0441\u0430\u043c\u043e\u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\u043c. \u041d\u0430\u0447\u0430\u043b \u0441\u043e \u0448\u043a\u043e\u043b\u044c\u043d\u044b\u0445 \u043a\u0443\u0440\u0441\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0442\u043e\u043c \u0438\u0437\u0443\u0447\u0430\u043b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438 \u0440\u0435\u0448\u0430\u043b \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043a \u0448\u043a\u043e\u043b\u044c\u043d\u044b\u043c \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u0430\u043c, \u0447\u0438\u0442\u0430\u043b \u043e \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435.<\/p>\n<p>\u0412 \u044f\u043d\u0432\u0430\u0440\u0435 2022 \u0433\u043e\u0434\u0430 \u043f\u043e \u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0441\u0442\u0438 \u0443\u0437\u043d\u0430\u043b \u043e \u043d\u0430\u0431\u043e\u0440\u0435 \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0443\u044e \u0448\u043a\u043e\u043b\u0443 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u043d\u0430\u0431\u043e\u0440\u0430 \u0443\u0441\u043f\u0435\u043b \u043f\u043e\u0434\u0430\u0442\u044c \u0437\u0430\u044f\u0432\u043a\u0443. \u0417\u0430 \u043c\u0435\u0441\u044f\u0446 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0441\u044f \u0441 aiohttp, \u043e\u0442\u043a\u0440\u044b\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u043c\u043e\u0449\u044c \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445, SQL \u0438 ORM. \u0421\u0442\u0430\u043b\u043e \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0449\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u041c\u0435\u0441\u0442\u0430\u043c\u0438 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0442\u0440\u0443\u0434\u043d\u043e \u0438 \u0431\u043e\u043b\u044c\u043d\u043e, \u043d\u043e \u043e\u043d\u043e \u0442\u043e\u0433\u043e \u0441\u0442\u043e\u0438\u043b\u043e. \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438\u0437\u0443\u0447\u0438\u043b \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 git.\u00a0<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u043c\u0435\u043d\u044f \u043f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u043b\u0438 \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u043d\u0430 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0443.\u00a0<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0441\u043b\u0443\u0447\u0430\u0435\u043c, \u0445\u043e\u0447\u0443 \u043f\u043e\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u0442\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0438 \u043d\u0430\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043a\u043e\u043b\u043b\u0435\u0433 \u0438\u0437 KTS, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441\u0432\u043e\u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0430\u0432\u043d\u0438\u043a\u0430 \u0421\u0430\u0448\u0443 ?.<\/p>\n<\/div>\n<\/details>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0440\u0430\u0431\u043e\u0442\u0435 Django<\/h2>\n<p>\u0417\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 Django \u044f \u043d\u0430\u0447\u0430\u043b \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0441 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u043d\u0435\u0439 \u0441\u0442\u0430\u0436\u0438\u0440\u043e\u0432\u043a\u0438. \u0420\u0430\u043d\u0435\u0435 \u0431\u044b\u043b \u043e\u043f\u044b\u0442 \u0441 aiohttp + SQLAlchemy\/GINO.\u00a0<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u0442\u044b\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 <a href=\"https:\/\/www.djangoproject.com\/\"><u>Django<\/u><\/a> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Django <a href=\"https:\/\/ru.wikipedia.org\/wiki\/ORM\"><u>ORM<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Python-\u043a\u043e\u0434\u0430 \u0432 \u044f\u0437\u044b\u043a SQL. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u00ab\u043d\u043e\u00bb. \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 N+1 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0435, \u0442\u0435\u043c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 Django \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#select-related\"><u>select_related<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#prefetch-related\"><u>prefetch_related<\/u> <\/a>(\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#prefetch-objects\"><u>Prefetch<\/u><\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/ref\/models\/querysets\/#only\"><u>only<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f API \u0438\u043c\u0435\u0435\u0442\u0441\u044f 2 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: <a href=\"https:\/\/habr.com\/ru\/post\/335158\/\"><u>REST API \u0438 GraphQL<\/u><\/a>. \u0412 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/graphql.org\/\"><u>GraphQL<\/u><\/a>.\u00a0<\/p>\n<p>REST API \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0440\u043e\u0433\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0411\u0414 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e (\u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c). GraphQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u043a\u043b\u0438\u0435\u043d\u0442 \u0441\u0430\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e. \u041c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u043b\u0430\u0442\u044c select_related \u0438 prefetch_related \u043f\u043e \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044f\u043c, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0441\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0431\u0443\u0434\u0443\u0442 \u043b\u0438\u0448\u043d\u0438\u0435 \u00ab\u0434\u0436\u043e\u0439\u043d\u044b\u00bb \u0438 \u0438\u0437 \u0411\u0414 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/h2>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u0437\u044f\u043b\u0441\u044f \u0437\u0430 \u0435\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0418\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 info (\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0435), \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043a\u043b\u044e\u0447\u0430\u043c \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0435 <code>_meta<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u0430, \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/docs.python.org\/3\/library\/functools.html\"><u>functools<\/u><\/a>.<\/p>\n<p>\u0412 <code>info<\/code> \u0432\u0441\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 CamelCase, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0438\u0445 \u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0443 <code>snake_case<\/code>. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/docs.python.org\/3\/library\/re.html\"><u>\u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/u><\/a>. \u0412 \u0438\u0442\u043e\u0433\u0435 <code>waitingAsyncDjango<\/code> \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <code>waiting_async_django<\/code>:<\/p>\n<pre><code class=\"python\">camel_case_pattern = re.compile(r\"(?&lt;!^)(?=[A-Z])\")  def string_to_snake_case(value: str) -> str: return camel_case_pattern.sub(\"_\", value).lower()<\/code><\/pre>\n<p>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0443\u0437\u043d\u0430\u0451\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u044f \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 GraphQL. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c <code>ast_to_dict<\/code>, \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0435\u0440\u0451\u043c \u0438\u0437 info:<\/p>\n<pre><code class=\"python\">from graphql.utils.ast_to_dict import ast_to_dict  def collect_gql_fields( node: dict, fragments: dict, snake_case: bool = True, ) -> dict[str, dict]: field = {} if node.get(\"selection_set\"): for leaf in node[\"selection_set\"][\"selections\"]: if leaf[\"kind\"] == \"Field\": key = leaf[\"name\"][\"value\"] if snake_case: key = string_to_snake_case(key) field.update({key: collect_gql_fields(leaf, fragments)}) elif leaf[\"kind\"] == \"FragmentSpread\": field.update( collect_gql_fields(fragments[leaf[\"name\"][\"value\"]], fragments) ) return field  def get_gql_fields( info: ResolveInfo, snake_case: bool = True, ) -> dict[str, dict]: fragments = {} node = ast_to_dict(info.field_asts[0]) for name, value in info.fragments.items(): fragments[name] = ast_to_dict(value) return collect_gql_fields(node, fragments, snake_case=snake_case)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>only<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_all_field_names(model: Type[models.Model]) -> list[str]: return [field.name for field in model._meta.fields]<\/code><\/pre>\n<p>\u0414\u043b\u044f <code>select_related<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 <em>many-to-one<\/em> \u0438 <em>one-to-one<\/em>, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u044d\u0442\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_fields_to_select( model: Type[models.Model], ) -> dict[str, Type[models.Model]]: fields = { field.name: field.related_model for field in model._meta.fields if field.many_to_one or field.one_to_one } related_fields = { field.name: field.related_model for field in model._meta.fields_map.values() if field.many_to_one or field.one_to_one } return fields | related_fields<\/code><\/pre>\n<p>\u0414\u043b\u044f <code>prefetch_related<\/code> \u0438 <code>Prefetch<\/code> \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 <em>one-to-many <\/em>\u0438<em> many-to-many<\/em>, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0435\u0432\u0435\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u044d\u0442\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"python\">@lru_cache def _get_model_fields_to_prefetch( model: Type[models.Model], ) -> dict[str, Type[models.Model]]: one_to_many = { field.name: field.related_model for field in model._meta.fields if field.one_to_many or field.many_to_many } many_to_many = { field.name: field.related_model  for field in model._meta.many_to_many } related_fields = { field.name: field.related_model for field in model._meta.fields_map.values() if field.one_to_many or field.many_to_many } return one_to_many | many_to_many | related_fields<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <em>dataclass<\/em>:<\/p>\n<pre><code class=\"python\">@dataclass class ModelFields: select_fields: list[str] prefetch_fields: list[str | Prefetch] only_fields: list[str]<\/code><\/pre>\n<p>\u0423\u0437\u043d\u0430\u0432 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u0442\u0438\u043f\u044b \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">def collect_model_fields( model: Type[models.Model], gql_fields: dict, prefix: str = \"\", ) -> ModelFields: all_field_names = _get_model_all_field_names(model) to_select = _get_model_fields_to_select(model) to_prefetch = _get_model_fields_to_prefetch(model)  select_fields, prefetch_fields, only_fields = [], [], []  # \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043f\u043e\u043b\u044f\u043c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 for field_name in gql_fields.keys(): # \u0447\u0435\u043c \u0433\u043b\u0443\u0431\u0436\u0435 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0442\u0435\u043c \u0434\u043b\u0438\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 location = prefix + field_name next_prefix = location + \"__\"      if field_name in to_select: # \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 - \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f many-to-one \u0438\u043b\u0438 one-to-one  # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 next_fields = collect_model_fields( to_select[field_name], gql_fields[field_name], prefix=next_prefix, )        # \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043a \u0443\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c if next_fields.only_fields: # \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u043b\u0430\u0442\u044c select_related # \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0438\u0437 \u043d\u0435\u0435 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0434\u043b\u044f .only(), # \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0422\u041e\u041b\u042c\u041a\u041e \u0434\u043b\u044f prefetch, # \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. select_fields.append(location) only_fields.extend(next_fields.only_fields)          select_fields.extend(next_fields.select_fields) prefetch_fields.extend(next_fields.prefetch_fields)        elif field_name in to_prefetch: # \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 - \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f one-to-many \u0438\u043b\u0438 many-to-many # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 next_fields = collect_model_fields( to_prefetch[field_name], gql_fields[field_name], prefix=next_prefix, )        # \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043a \u0443\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c prefetch_fields.extend(next_fields.prefetch_fields) if next_fields.select_fields: # \u0435\u0441\u043b\u0438 \u0443 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u043f\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 # \u0441 \u0442\u0438\u043f\u043e\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f many-to-one \u0438\u043b\u0438 one-to-one, # \u0442\u043e \u0434\u043b\u044f \u0431\u041e\u043b\u044c\u0448\u0435\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 Prefetch related_select_fields = [ i.removeprefix(next_prefix) for i<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-393774","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/393774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=393774"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/393774\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=393774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=393774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=393774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}