{"id":394175,"date":"2024-06-29T11:27:07","date_gmt":"2024-06-29T11:27:07","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=394175"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=394175","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 Django, DRF<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441. \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 habr. \u041d\u0435 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u043d\u043e \u0434\u0443\u043c\u0430\u044e, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043b\u043e\u0445\u043e, \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0435\u0435 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0443\u0432\u0438\u0434\u0435\u043b.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430 \u0434\u043d\u044f\u0445 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044f \u0438 \u0440\u0435\u0448\u0438\u043b \u0443\u0431\u0438\u0442\u044c \u0434\u0432\u0443\u0445 \u0437\u0430\u0439\u0446\u0435\u0432 \u0441\u0440\u0430\u0437\u0443: \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<h2>\u0417\u0430\u0434\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e \u043c\u044b \u0438\u043c\u0435\u0435\u043c:<\/p>\n<blockquote>\n<p><em>\u0412\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447a &#8212; \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a<\/p>\n<p><\/em><strong><em>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443:<sub><br \/><\/sub><br \/><\/em><\/strong>\u2013 \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441 \u043f\u043e\u043b\u0435\u043c \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0438\u043b\u0438 API \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438<br \/>\u2013 \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0430\u043c<br \/>\u2013 \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043f\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 URL<br \/>\u2013 \u0422\u043e\u043a\u0435\u043d \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043b\u0438\u043d\u043e\u0439 6 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0431\u0443\u043a\u0432 (\u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430) \u0438 \u0446\u0438\u0444\u0440<br \/>\u2013 \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Django \u0438\u043b\u0438 Django Rest Framework<br \/>\u2013 \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0433\u0438\u0442-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/p>\n<\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c url, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u201c<a href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/<\/u><\/a>\u201d, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 (\u0438\u0437 6 \u0446\u0438\u0444\u0440 \u0438 \u0431\u0443\u043a\u0432 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u201ctR5Gq0\u201d. \u0418 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u043c\u0443 url (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <a href=\"https:\/\/my_domain.ru\/tR5Gq0\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/tR5Gq0<\/u><\/a><u>)<\/u> \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0441 \u043d\u0430 <a href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/<\/u><\/a>.<\/p>\n<p>\u042f \u0432\u044b\u0431\u0440\u0430\u043b \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 API, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043c\u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043b\u0438\u0436\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0443 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u0443\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0423\u0441\u043b\u043e\u0432\u043d\u043e, \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438:<br \/><\/strong><\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c post \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 url \u0430\u0434\u0440\u0435\u0441\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c (\u2018full_url\u2019).<\/p>\n<\/li>\n<li>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0430 \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u043d\u0443\u0442\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443(\u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438) \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.\u00a0<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 url.<\/strong><\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439. \u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u043f\u0430\u0440\u0430 <code>(\u2018full_url\u2019 \u2192 \u2018short_url\u2019)<\/code> \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u043c.\u00a0<\/p>\n<p>\u041f\u043e\u0433\u043d\u0430\u043b\u0438!<\/p>\n<h2>\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h2>\n<p>\u042f \u043d\u0430\u0447\u0438\u043d\u0430\u044e \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0432 Git<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440.\u00a0<\/p>\n<p><code>git clone https:\/\/github.com\/&lt;user_name>\/&lt;rep_name><\/code><\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u0430\u043f\u043a\u0443.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p><code>python -m venv venv<br \/> source venv\/bin\/activate<\/code><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Django \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 (\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0432\u0435\u0440\u0441\u0438\u044e 3.2, \u0445\u043e\u0442\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0434\u043e\u0448\u043b\u0430 \u0431\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u043e\u0447\u0442\u0438 \u043b\u044e\u0431\u0430\u044f)<\/p>\n<p><code>pip install Django==3.2<\/code><\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b requirements.txt:<\/p>\n<p><code>pip freeze > requirements.txt<\/code><\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 Django-\u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<p><code>django-admin startproject link_shortner<\/code><\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0438\u0437 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u043f\u0430\u043f\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<p><code>python manage.py runserver<\/code><\/p>\n<p>\u041d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0442\u0438\u043f\u0430:<\/p>\n<p><code>Watching for file changes with StatReloader<br \/>Performing system checks...<\/p>\n<p>System check identified no issues (0 silenced).<\/p>\n<p>You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.<\/p>\n<p>Run 'python manage.py migrate' to apply them.<br \/>March 05, 2021 - 04:27:33<br \/>Django version 2.2.19, using settings 'link_shortner.settings'<br \/>Starting development server at http:\/\/127.0.0.1:8000\/<br \/>Quit the server with CONTROL-C.<\/code>\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0431\u0440\u0430\u0439\u0437\u0435\u0440\u0435 <a href=\"http:\/\/127.0.0.1:8000\/\" rel=\"noopener noreferrer nofollow\">http:\/\/127.0.0.1:8000<\/a> \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d27\/a82\/965\/d27a829652383e5d368aaec3fb82f539.png\" width=\"2112\" height=\"1658\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d27\/a82\/965\/d27a829652383e5d368aaec3fb82f539.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0430\u043a \u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c, \u043c\u044b \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043a, \u0438 \u0438\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 API:<\/p>\n<p><code>python3 manage.py startapp api<\/code><\/p>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a settings.py:<\/p>\n<pre><code class=\"python\">INSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'api'  # \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 ]<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u0412\u0441\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u00a0<\/p>\n<h2>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 ORM \u043c\u043e\u0434\u0435\u043b\u0438<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c ORM \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432.<br \/>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b <code>link_shorter\/api\/models.py<\/code> \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"python\">import random  # \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c random \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438  from django.conf import settings  # \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0438\u0437 \u0444\u0430\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a from django.db import models  class Tokens(models.Model):     \"\"\"\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432\"\"\"     full_url = models.URLField(unique=True)     short_url = models.CharField(         max_length=20,         unique=True,         db_index=True,         blank=True     )     requests_count = models.IntegerField(default=0)     created_date = models.DateTimeField(auto_now_add=True)     is_active = models.BooleanField(default=True)      class Meta:         ordering = ('-created_date',)  # \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430      def save(self, *args, **kwargs):         \"\"\"         \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438,         \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.         \u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c         \"\"\"         if not self.short_url:             while True:  # \u0446\u0438\u043a\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443                 self.short_url = ''.join(                     random.choices(                         settings.CHARACTERS,  # \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a                         k=settings.TOKEN_LENGTH  # \u0434\u043b\u0438\u043d\u0443 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0442\u043e\u0436\u0435                     )                 )                 if not Tokens.objects.filter(  # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c                     short_url=self.short_url                 ).exists():                     break         super().save(*args, **kwargs)      def __str__(self) -> str:         return f'{self.short_url} -> {self.full_url}' <\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>full_url<\/summary>\n<div class=\"spoiler__content\">\n<p>full_url &#8212; \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430. \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c URLField \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0447\u0435\u0433\u043e-\u0442\u043e \u0438\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>short_url<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>short_url<\/strong> \u2013 \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430. CharField \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043d\u0435 \u0432\u0435\u0441\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url, \u0430 \u043b\u0438\u0448\u044c \u0442\u0430 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0434\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043c\u0435\u043d\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u043b\u044f:<\/p>\n<p><strong>max_length=20<\/strong>, # \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 20 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0422\u0430\u043a\u0438\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0432 \u0422\u0417 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043d\u043e \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u0447\u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u0438\u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 20 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445(6 \u0446\u0438\u0444\u0440 \u0438\u043b\u0438 \u0431\u0443\u043a\u0432 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430) \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c 56 800 235 584 url-\u043e\u0432 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u0435.<\/p>\n<p><strong>unique=True<\/strong>, # \u0442\u0443\u0442 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c<\/p>\n<p><strong>db_index=True<\/strong>, # \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043b\u044e short_url<\/p>\n<p><strong>blank=True<\/strong> # \u043f\u043e\u043b\u0435 short_url \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u0430\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>requests_count<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>requests_count<\/strong> \u2013 \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>created_date<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>created_date<\/strong> &#8212; \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u0434\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u043d\u0435\u0439 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043d\u043e \u043c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0435\u0448\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0441\u0441\u044b\u043b\u043a\u0438 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u043d\u0430\u0442\u044c \u0434\u0430\u0442\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>is_active<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>is_active<\/strong> \u2013 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0438\u043b\u0438 \u043d\u0435\u0442. \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f True \u0438\u043b\u0438 False.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0435\u0442\u043e\u0434 save. <\/p>\n<pre><code class=\"python\">def save(self, *args, **kwargs):         \"\"\"         \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438,         \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.         \u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c         \"\"\"         if not self.short_url:             while True:  # \u0446\u0438\u043a\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443                 self.short_url = ''.join(                     random.choices(                         settings.CHARACTERS,  # \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a                         k=settings.TOKEN_LENGTH  # \u0434\u043b\u0438\u043d\u0443 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0442\u043e\u0436\u0435                     )                 )                 if not Tokens.objects.filter(  # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c                     short_url=self.short_url                 ).exists():                     break         super().save(*args, **kwargs)<\/code><\/pre>\n<p>\u041e\u043d \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043b \u0435\u0435 \u0432 \u0442\u0435\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.\u00a0<\/p>\n<p>\u0421 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0432\u0440\u043e\u0434\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0432 \u0444\u0430\u0439\u043b <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a>. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a> \u0438 \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0433\u0434\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u043d\u0438\u0437\u0443:<\/p>\n<pre><code class=\"python\"># \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0422\u043e\u043a\u0435\u043d\u0430(\u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438) CHARACTERS = 'ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz234567890' TOKEN_LENGTH = 6<\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438. \u0413\u043e\u0442\u043e\u0432\u043e.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0438<\/h3>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0430\u043d\u0435\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e Django \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0443\u0440\u043b\u0430 <code>admin\/<\/code>, \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430\u0441\u044c \u043d\u0430\u0448\u0430 \u0430\u0434\u043c\u0438\u043d\u043a\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b admin.py \u0432 \u043f\u0430\u043f\u043a\u0435 api \u0438 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"python\">from django.contrib import admin  from .models import Tokens  # \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c Tokens   @admin.register(Tokens) class TokenAdmin(admin.ModelAdmin):     \"\"\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0438 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0422\u043e\u043a\u0435\u043d\u043e\u0432\"\"\"     list_display = (  # \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0435\u0439         'full_url',         'short_url',         'requests_count',         'created_date',         'is_active'     )     search_fields = ('full_url', 'short_url')  # \u043f\u043e\u043b\u044f \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d     ordering = ('-created_date',)  # \u0432\u0441\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0431\u044b\u043b\u0438 \u0441\u0432\u0435\u0440\u0445\u0443<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a \u043a\u043e\u0434\u0443. <\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438. \u0418\u0437 \u043f\u0430\u043f\u043a\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c manage.py \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p><code>python manage.py makemigrations<\/code><\/p>\n<p><code>python manage.py migrate<\/code><\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u0411\u0414 \u0441\u043e\u0437\u0434\u0430\u043d\u0430, \u0430\u0434\u043c\u0438\u043d\u043a\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0443\u043f\u0435\u0440\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0443:<\/p>\n<p>\u0418\u0437 \u043f\u0430\u043f\u043a\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c manage.py \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p><code>python manage.py createsuperuser<\/code><\/p>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (username, email, password)<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<p><code>python manage.py runserver<\/code><\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 <a href=\"http:\/\/127.0.0.1:8000\/admin\/\" rel=\"noopener noreferrer nofollow\">http:\/\/127.0.0.1:8000\/admin\/<\/a><\/p>\n<p>\u0412\u0443\u0430\u043b\u044f.<\/p>\n<h2>TTD (Test-Driven Development)<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u043a\u0430\u043a \u0435\u0432\u0430\u043d\u0433\u0435\u043b\u0438\u0441\u0442 TTD (Test-Driven Development) \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0447\u0442\u043e \u0436\u0435 \u043c\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u043f\u0430\u043f\u043a\u0435 API c\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b <a href=\"http:\/\/tests.py\" rel=\"noopener noreferrer nofollow\">tests.py<\/a> \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c:<\/p>\n<pre><code class=\"python\">from django.test import TestCase from rest_framework.test import APITestCase  from .models import Tokens   class TestAPI(APITestCase):     \"\"\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c POST \u0437\u0430\u043f\u0440\u043e\u0441\u044b\"\"\"     url = '\/api\/tokens\/'      def setUp(self) -> None:         Tokens.objects.create(             full_url='https:\/\/ya.ru\/',             short_url='aEdj01',         )      def test_token_get(self):         \"\"\"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430\"\"\"         existing_data = {             'full_url': 'https:\/\/ya.ru\/'         }         response_get = self.client.post(self.url, data=existing_data)         result_get = response_get.json()          self.assertEqual(response_get.status_code, 200)         self.assertEqual(Tokens.objects.all().count(), 1)         self.assertEqual(result_get['full_url'], 'https:\/\/ya.ru\/')         self.assertEqual(result_get['short_url'], 'aEdj01')         self.assertIsInstance(result_get, dict)         self.assertEqual(len(result_get), 6)      def test_token_create(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0431\u0435\u0437 \u044f\u0432\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438         \u0438 \u0441 \u044f\u0432\u043d\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438         \"\"\"         creation_data = {             'full_url': 'http:\/\/post.url.test.ru'         }         creation_full_data = {             'full_url': 'http:\/\/test.ru',             'short_url': 'Q2We34'         }         response_create = self.client.post(self.url, data=creation_data)         result_create = response_create.json()          response_create_with_short_url = self.client.post(             self.url, data=creation_full_data         )         result_create_with_short_url = response_create_with_short_url.json()          self.assertEqual(response_create.status_code, 201)         self.assertEqual(result_create['full_url'], 'http:\/\/post.url.test.ru')         self.assertEqual(len(result_create['short_url']), 6)         self.assertIsInstance(result_create, dict)         self.assertEqual(Tokens.objects.all().count(), 3)         self.assertEqual(len(result_create), 6)         self.assertEqual(             result_create_with_short_url['full_url'],             'http:\/\/test.ru',             msg='\u041e\u0448\u0438\u0431\u043a\u0430 full_url'         )         self.assertEqual(             result_create_with_short_url['short_url'],             'Q2We34',             msg='\u041e\u0448\u0438\u0431\u043a\u0430 short_url'         )   class TestRedirection(TestCase):     \"\"\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c GET \u0437\u0430\u043f\u0440\u043e\u0441\u044b\"\"\"     active_url = '\/aEdj01'     deactive_url = '\/q2Nb23'      def setUp(self) -> None:         Tokens.objects.create(             full_url='https:\/\/ya.ru\/',             short_url='aEdj01',         )          Tokens.objects.create(             full_url='https:\/\/stackoverflow.com\/',             short_url='q2Nb23',             is_active=False         )      def test_redirection(self):         \"\"\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044e\"\"\"         response = self.client.get(self.active_url)          self.assertEqual(response.status_code, 302)         self.assertEqual(response.url, 'https:\/\/ya.ru\/')      def test_response_counter(self):         \"\"\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0442\u043e\u043a\u0435\u043d\u0430\"\"\"         self.assertEqual(             Tokens.objects.get(short_url='aEdj01').requests_count, 0         )         self.client.get(self.active_url)         self.assertEqual(             Tokens.objects.get(short_url='aEdj01').requests_count, 1         )         self.assertEqual(             Tokens.objects.get(short_url='q2Nb23').requests_count, 0         )         self.client.get(self.deactive_url)         self.assertEqual(             Tokens.objects.get(short_url='q2Nb23').requests_count, 0         )      def test_deactive_url(self):         \"\"\"\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b\"\"\"         response = self.client.get(self.deactive_url)         self.assertEqual(response.content, b'Token is no longer available')<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0442\u043e\u0442 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0442\u0435\u0441\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0432\u0441\u0435 \u0442\u0430\u043a\u0438 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u043f\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u0441\u0442\u044b \u0433\u043e\u0442\u043e\u0432\u044b, \u043f\u043e\u0440\u0430 \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c.<\/p>\n<p>\u041a\u0430\u043a \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435, \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c POST \u0437\u0430\u043f\u0440\u043e\u0441 \u0444\u043e\u0440\u043c\u0430\u0442\u0430:<\/p>\n<pre><code class=\"json\">{ \u201cfull_url\u201d: \u201chttps:\/\/ya.ru\u201d }<\/code><\/pre>\n<p>\u0438\u043b\u0438 <\/p>\n<pre><code class=\"json\">{ \u201cfull_url\u201d: \u201chttps:\/\/ya.ru\u201d \u201cshort_url\u201d: \u201cQ54gP2\u201d }<\/code><\/pre>\n<p>\u0410 \u0432 \u043e\u0442\u0432\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u0430. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0438\u0435:<\/p>\n<pre><code class=\"json\">{     \"id\": 34,     \"full_url\": \"https:\/\/ya.ru\/\",     \"short_url\": \"PQbOuy\",     \"requests_count\": 0,     \"created_date\": \"2023-02-03T09:26:16.421135Z\",     \"is_active\": true }<\/code><\/pre>\n<h2>\u0421\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440<\/h2>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435  \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Python, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0432 \u043f\u0430\u043f\u043a\u0435 api \u0444\u0430\u0439\u043b serializers.py:<\/p>\n<pre><code class=\"python\">from rest_framework import serializers, status  from .models import Tokens   class TokenSerializer(serializers.ModelSerializer):     \"\"\"     \u0421\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432:      \u0412 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0435 \u0443\u0431\u0440\u0430\u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f full_url,     \u043d\u043e \u043e\u043d\u0430 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043c\u043e\u0434\u0435\u043b\u0438.     \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b is_valid \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043b \u0434\u0430\u043d\u043d\u044b\u0435     \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u0440\u0438 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u0435.     \"\"\"      class Meta:         model = Tokens         fields = '__all__'         extra_kwargs = {'full_url': {'validators': []}}      def create(self, validated_data):         \"\"\"         \u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 create:         \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d         \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043e.         \"\"\"         full_url = validated_data['full_url']         token, created = Tokens.objects.get_or_create(full_url=full_url)         if created:             status_code = status.HTTP_201_CREATED         else:             status_code = status.HTTP_200_OK         return token, status_code<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e (\u0432\u0441\u0435 \u0442\u0430\u043a\u0438 \u043a\u043e\u0434 \u043f\u0438\u0441\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044f). \u041c\u043e\u0433\u0443 \u043b\u0438\u0448\u044c \u0432 \u043e\u0431\u0449\u0438\u0445 \u0447\u0435\u0440\u0442\u0430\u0445 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0442\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043c\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043e\u0442 ModelSerializer, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u043c \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0430\u043c\u0438\u043c \u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u043e\u0442 \u043d\u0430\u0441 \u043b\u0438\u0448\u044c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0438 \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a \u0441\u0442\u0435\u0440\u0438\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0443, \u043d\u043e \u0435\u0441\u043b\u0438 \u0447\u0442\u043e \u0433\u043e\u0442\u043e\u0432 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<h3>View-\u043a\u043b\u0430\u0441\u0441<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u0441 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u0440\u043e\u0434\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b <a href=\"http:\/\/views.py\" rel=\"noopener noreferrer nofollow\">views.py<\/a>:\u00a0<\/p>\n<pre><code class=\"python\">from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView  from .serializers import TokenSerializer   class TokenAPIView(APIView):     \"\"\"\u0412\u044c\u044e\u0445\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438\"\"\"      def post(self, request):         serializer = TokenSerializer(data=request.data)         if serializer.is_valid(raise_exception=True):             token, status_code = serializer.create(                 validated_data=serializer.validated_data             )             return Response(TokenSerializer(token).data, status=status_code)         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 View-\u043a\u043b\u0430\u0441\u0441 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 APIView. \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u043e \u043d\u0430\u0448\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 api\/tokens\/ \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e POST \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043e\u043f\u0438\u0448\u0435\u043c \u0432\u043e view-\u043a\u043b\u0430\u0441\u0441\u0435 \u043c\u0435\u0442\u043e\u0434 post. \u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e, \u043e\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043c\u0435\u0442\u043e\u0434 create (\u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0438\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0431\u0434) \u0438 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0438 http-\u0441\u0442\u0430\u0442\u0443\u0441 \u043e\u0442\u0432\u0435\u0442\u0430. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0433\u043e\u0442\u043e\u0432.<\/p>\n<h2>URLconf<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 <a href=\"http:\/\/urls.py\" rel=\"noopener noreferrer nofollow\">urls.py<\/a>.<\/p>\n<p>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u043d\u043f\u043e\u0438\u043d\u0442\u043e\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \/api\/tokens\/ (\u0432\u044b \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0442\u043e\u0447\u043a\u0443). \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c POST \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 <a href=\"https:\/\/my_domain.ru\/api\/tokens\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/api\/tokens\/<\/u><\/a> \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043a\u0435\u043d \u0441 \u043f\u0430\u0440\u043e\u0439 (<em>\u2018full_url\u2019 \u2192 \u2018short_url\u2019<\/em>).<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u043e\u043f\u0438\u0448\u0435\u043c \u0432 \u043a\u043e\u0434\u0435. \u0412\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u043e\u043c <a href=\"http:\/\/urls.py\" rel=\"noopener noreferrer nofollow\">urls.py<\/a> \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0435\u043c\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 \/link_shorter\/link_shorter (\u0442\u0430\u043c \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a>), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0435\u0433\u043e:<\/p>\n<pre><code class=\"python\">from django.contrib import admin from django.urls import include, path  urlpatterns = [     path('admin\/', admin.site.urls),          path('api\/', include('api.urls')),   ]<\/code><\/pre>\n<p># \u0437\u0430\u043f\u0440\u043e\u0441 <a href=\"https:\/\/my_domain.ru\/api\/tokens\/\" rel=\"noopener noreferrer nofollow\">https:\/\/my_domain.ru\/<\/a>admin\/ \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0443\u0435\u0442 \u043d\u0430\u0441 \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0443<\/p>\n<p># \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 <a href=\"https:\/\/my_domain.ru\/api\/tokens\/\" rel=\"noopener noreferrer nofollow\">https:\/\/my_domain.ru<\/a>\/api\/\u2026 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0444\u0430\u0439\u043b <a href=\"http:\/\/urls.py\" rel=\"noopener noreferrer nofollow\">urls.py<\/a> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f api. \u041a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0442\u043e\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c.\u00a0<\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b <a href=\"http:\/\/urls.py\" rel=\"noopener noreferrer nofollow\">urls.py<\/a> \u0432 \u043f\u0430\u043f\u043a\u0435 api:<\/p>\n<pre><code class=\"python\">from django.urls import path  from .views import TokenAPIView  app_name = 'api'   urlpatterns = [     path('tokens\/', TokenAPIView.as_view()), ]<\/code><\/pre>\n<p>\u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u043f\u0438\u0441\u0430\u043b \u0432\u044b\u0448\u0435, \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 <a href=\"https:\/\/my_domain.ru\/api\/tokens\/\" rel=\"noopener noreferrer nofollow\">https:\/\/my_domain.ru<\/a>\/api\/\u2026 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u044e\u0434\u0430, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u0442\u0443 \u0447\u0430\u0441\u0442\u044c \u043f\u0443\u0442\u0438 \u043d\u0430\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u0412\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 as_view() \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e view(), \u043a\u043e\u0442\u043e\u0440\u0443\u044e Django \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u0441 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c &#8216;tokens\/&#8217;.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u0432 <code>path('tokens\/', TokenAPIView.as_view())<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 <code>https:\/\/my_domain.ru\/api\/tokens<\/code> \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c TokenAPIView \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0433\u043e\u0442\u043e\u0432, \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0430\u0439\u0442.<\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u043c \u0447\u0442\u043e\u0431\u044b \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043d\u0430 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <a href=\"https:\/\/my_domain.ru\/Th45Qw\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/Th45Qw<\/u><\/a>) \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b\u0430 \u0432 \u0431\u0430\u0437\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043a \u0438 \u0442\u0430\u043a\u043e\u0439 \u0442\u043e\u043a\u0435\u043d \u0435\u0441\u0442\u044c, \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u043d\u044b\u0439 url.<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0438 \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435. \u041d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e <a href=\"http:\/\/service.py\" rel=\"noopener noreferrer nofollow\">service.py<\/a><\/p>\n<pre><code class=\"python\">from django.http import HttpResponse from django.shortcuts import redirect  from .models import Tokens   def get_full_url(url: str) -> str:     \"\"\"     \u0414\u043e\u0441\u0442\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043f\u043e short_url     \u0415\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0435\u0442 \u0432 \u0431\u0430\u0437\u0435 \u0438\u043b\u0438 \u043e\u043d\u0430 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0430     \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443.     \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043a, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 1     \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443.     \"\"\"     try:  # \u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u043d\u0435\u0442 \u0440\u0430\u0439\u0437\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c \u043d\u043e \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d - \u0440\u0430\u0439\u0437\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443.         token = Tokens.objects.get(short_url__exact=url)         if not token.is_active:             raise KeyError('Token is no longer available')     except Tokens.DoesNotExist:         raise KeyError('Try another url. No such urls in DB')     token.requests_count += 1  # \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c 1 \u043a \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0443 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0434\u0430\u0447\u043d\u043e\u0433\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430     token.save() # \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0411\u0414      return token.full_url   def redirection(request, short_url):     \"\"\"\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435\"\"\"     try:         full_link = get_full_url(short_url)  # \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435         return redirect(full_link)  # \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435     except Exception as e:         return HttpResponse(e.args)  # \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u0442\u0430\u043a, \u0440\u0430\u0439\u0437\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0443\u0442\u0438, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u0441\u0442\u0440\u043e\u043a \u0432 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0444\u0430\u0439\u043b <a href=\"http:\/\/urls.py\" rel=\"noopener noreferrer nofollow\">urls.py<\/a> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a> \u0438 <a href=\"http:\/\/wsgi.py\" rel=\"noopener noreferrer nofollow\">wsgi.py<\/a>):<\/p>\n<pre><code class=\"python\">from api import services  # \u043d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 from django.contrib import admin from django.urls import include, path  urlpatterns = [     path('admin\/', admin.site.urls),     path('api\/', include('api.urls')),     path('&lt;str:short_url>', services.redirection),  # \u043d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 ]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0435 \u043d\u0430 <a href=\"https:\/\/my_domain.ru\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/<\/u><\/a>???? \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <strong>redirection<\/strong> \u0430 \u043e\u043d\u0430 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0439 \u0441\u0430\u0439\u0442 \u043b\u0438\u0431\u043e \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 (\u0435\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0435\u0442 \u0432 \u0431\u0430\u0437\u0435 \u0438\u043b\u0438 \u043e\u043d\u0430 \u043f\u043e \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0443\u0436\u0435 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0430).<\/p>\n<h2>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a<\/h2>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u044b: <code>python manage.py test<\/code>. \u041f\u0443\u0442\u044c \u043a \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, python \u0441\u0430\u043c \u043d\u0430\u0439\u0434\u0435\u0442 \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441\u043e \u0441\u043b\u043e\u0432\u0430 test \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0438\u0445.<\/p>\n<p><code>Creating test database for alias 'default'...<br \/>System check identified no issues (0 silenced).<br \/>....<br \/>----------------------------------------------------------------------<br \/>Ran 4 tests in 0.034s<br \/>OK<br \/>Destroying test database for alias 'default'...<\/code><\/p>\n<p>\u0422\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0448\u043b\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>python manage.py test -v2<\/code><\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0432 POSTMAN.<\/p>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c POST \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \/api\/tokens\/ \u0432 \u0442\u0435\u043b\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c url \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/331\/34f\/780\/33134f780c7903958e28eb47c8c577b9.png\" width=\"1718\" height=\"1152\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/331\/34f\/780\/33134f780c7903958e28eb47c8c577b9.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0448\u0435\u043b \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u0434 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u043e\u043d 201 (created), \u043d\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u043e\u0441\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u044d\u0442\u0438\u043c \u0436\u0435 \u0443\u0440\u043b\u043e\u043c, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0435 \u0436\u0435 \u0434\u0430\u043d\u043d\u044b\u0435(\u0442\u0430\u043a \u043a\u0430\u043a \u0442\u043e\u043a\u0435\u043d \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d), \u043d\u043e \u0441\u0442\u0430\u0442\u0443\u0441 \u043a\u043e\u0434 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 200 (ok).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/afb\/6d4\/e60\/afb6d4e601a02faf7cfade75a9595f68.png\" width=\"1722\" height=\"1092\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/afb\/6d4\/e60\/afb6d4e601a02faf7cfade75a9595f68.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0438 \u0441\u0440\u0430\u0437\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/edc\/a20\/dde\/edca20ddef1bf362335883f1f127172f.png\" width=\"1626\" height=\"1100\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/edc\/a20\/dde\/edca20ddef1bf362335883f1f127172f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c, \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0441 \u044f\u0432\u043d\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438. \u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435: <a href=\"https:\/\/my_domain.ru\/R3u2N1\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/R3u2N1<\/u><\/a> \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u0432\u0432\u043e\u0434 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u0430\u0439\u0442 \u0411\u0435\u0433\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 (<a href=\"https:\/\/runc.run\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/runc.run<\/u><\/a>).<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435, \u0443\u0432\u0435\u0440\u0435\u043d, \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0443 \u0432\u0430\u0448\u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a \u043f\u043e\u0441\u0442\u0443. \u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u044d\u0442\u043e \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u0441\u0442 \u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043e\u0442\u043a\u0440\u044b\u0442 \u043a \u043b\u044e\u0431\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u0435:) \u0421\u043f\u0430\u0441\u0438\u0431\u043e.<\/p>\n<p><a href=\"https:\/\/github.com\/okazivaetsya\/link_shortener\" rel=\"noopener noreferrer nofollow\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 GitHub-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c<\/a><\/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\/718800\/\"> https:\/\/habr.com\/ru\/articles\/718800\/<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441. \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 habr. \u041d\u0435 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u043d\u043e \u0434\u0443\u043c\u0430\u044e, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043b\u043e\u0445\u043e, \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0435\u0435 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0443\u0432\u0438\u0434\u0435\u043b.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430 \u0434\u043d\u044f\u0445 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044f \u0438 \u0440\u0435\u0448\u0438\u043b \u0443\u0431\u0438\u0442\u044c \u0434\u0432\u0443\u0445 \u0437\u0430\u0439\u0446\u0435\u0432 \u0441\u0440\u0430\u0437\u0443: \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<h2>\u0417\u0430\u0434\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e \u043c\u044b \u0438\u043c\u0435\u0435\u043c:<\/p>\n<blockquote>\n<p><em>\u0412\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447a &#8212; \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a<\/p>\n<p><\/em><strong><em>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443:<sub><br \/><\/sub><br \/><\/em><\/strong>\u2013 \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441 \u043f\u043e\u043b\u0435\u043c \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0438\u043b\u0438 API \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438<br \/>\u2013 \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0430\u043c<br \/>\u2013 \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043f\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 URL<br \/>\u2013 \u0422\u043e\u043a\u0435\u043d \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043b\u0438\u043d\u043e\u0439 6 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0431\u0443\u043a\u0432 (\u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430) \u0438 \u0446\u0438\u0444\u0440<br \/>\u2013 \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Django \u0438\u043b\u0438 Django Rest Framework<br \/>\u2013 \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0433\u0438\u0442-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/p>\n<\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c url, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u201c<a href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/<\/u><\/a>\u201d, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 (\u0438\u0437 6 \u0446\u0438\u0444\u0440 \u0438 \u0431\u0443\u043a\u0432 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u201ctR5Gq0\u201d. \u0418 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u043c\u0443 url (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <a href=\"https:\/\/my_domain.ru\/tR5Gq0\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/my_domain.ru\/tR5Gq0<\/u><\/a><u>)<\/u> \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0441 \u043d\u0430 <a href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/habr.com\/ru\/company\/southbridge\/blog\/714358\/<\/u><\/a>.<\/p>\n<p>\u042f \u0432\u044b\u0431\u0440\u0430\u043b \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 API, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043c\u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043b\u0438\u0436\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0443 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u0443\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0423\u0441\u043b\u043e\u0432\u043d\u043e, \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438:<br \/><\/strong><\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c post \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 url \u0430\u0434\u0440\u0435\u0441\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c (\u2018full_url\u2019).<\/p>\n<\/li>\n<li>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0430 \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u043d\u0443\u0442\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443(\u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438) \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.\u00a0<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043f\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 url.<\/strong><\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439. \u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u043f\u0430\u0440\u0430 <code>(\u2018full_url\u2019 \u2192 \u2018short_url\u2019)<\/code> \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u043c.\u00a0<\/p>\n<p>\u041f\u043e\u0433\u043d\u0430\u043b\u0438!<\/p>\n<h2>\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h2>\n<p>\u042f \u043d\u0430\u0447\u0438\u043d\u0430\u044e \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0432 Git<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440.\u00a0<\/p>\n<p><code>git clone https:\/\/github.com\/&lt;user_name>\/&lt;rep_name><\/code><\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u0430\u043f\u043a\u0443.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p><code>python -m venv venv<br \/> source venv\/bin\/activate<\/code><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Django \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 (\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0432\u0435\u0440\u0441\u0438\u044e 3.2, \u0445\u043e\u0442\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0434\u043e\u0448\u043b\u0430 \u0431\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u043e\u0447\u0442\u0438 \u043b\u044e\u0431\u0430\u044f)<\/p>\n<p><code>pip install Django==3.2<\/code><\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b requirements.txt:<\/p>\n<p><code>pip freeze > requirements.txt<\/code><\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 Django-\u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<p><code>django-admin startproject link_shortner<\/code><\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0438\u0437 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u043f\u0430\u043f\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<p><code>python manage.py runserver<\/code><\/p>\n<p>\u041d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0442\u0438\u043f\u0430:<\/p>\n<p><code>Watching for file changes with StatReloader<br \/>Performing system checks...<\/p>\n<p>System check identified no issues (0 silenced).<\/p>\n<p>You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.<\/p>\n<p>Run 'python manage.py migrate' to apply them.<br \/>March 05, 2021 - 04:27:33<br \/>Django version 2.2.19, using settings 'link_shortner.settings'<br \/>Starting development server at http:\/\/127.0.0.1:8000\/<br \/>Quit the server with CONTROL-C.<\/code>\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0431\u0440\u0430\u0439\u0437\u0435\u0440\u0435 <a href=\"http:\/\/127.0.0.1:8000\/\" rel=\"noopener noreferrer nofollow\">http:\/\/127.0.0.1:8000<\/a> \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0430\u043a \u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c, \u043c\u044b \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043a, \u0438 \u0438\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 API:<\/p>\n<p><code>python3 manage.py startapp api<\/code><\/p>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a settings.py:<\/p>\n<pre><code class=\"python\">INSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'api'  # \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 ]<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u0412\u0441\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u00a0<\/p>\n<h2>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 ORM \u043c\u043e\u0434\u0435\u043b\u0438<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c ORM \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432.<br \/>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b <code>link_shorter\/api\/models.py<\/code> \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"python\">import random  # \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c random \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438  from django.conf import settings  # \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0438\u0437 \u0444\u0430\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a from django.db import models  class Tokens(models.Model):     \"\"\"\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432\"\"\"     full_url = models.URLField(unique=True)     short_url = models.CharField(         max_length=20,         unique=True,         db_index=True,         blank=True     )     requests_count = models.IntegerField(default=0)     created_date = models.DateTimeField(auto_now_add=True)     is_active = models.BooleanField(default=True)      class Meta:         ordering = ('-created_date',)  # \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430      def save(self, *args, **kwargs):         \"\"\"         \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438,         \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.         \u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c         \"\"\"         if not self.short_url:             while True:  # \u0446\u0438\u043a\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443                 self.short_url = ''.join(                     random.choices(                         settings.CHARACTERS,  # \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a                         k=settings.TOKEN_LENGTH  # \u0434\u043b\u0438\u043d\u0443 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0442\u043e\u0436\u0435                     )                 )                 if not Tokens.objects.filter(  # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c                     short_url=self.short_url                 ).exists():                     break         super().save(*args, **kwargs)      def __str__(self) -> str:         return f'{self.short_url} -> {self.full_url}' <\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>full_url<\/summary>\n<div class=\"spoiler__content\">\n<p>full_url &#8212; \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430. \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c URLField \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0447\u0435\u0433\u043e-\u0442\u043e \u0438\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>short_url<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>short_url<\/strong> \u2013 \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430. CharField \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043d\u0435 \u0432\u0435\u0441\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url, \u0430 \u043b\u0438\u0448\u044c \u0442\u0430 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0434\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043c\u0435\u043d\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u043b\u044f:<\/p>\n<p><strong>max_length=20<\/strong>, # \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 20 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0422\u0430\u043a\u0438\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0432 \u0422\u0417 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043d\u043e \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u0447\u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u0438\u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 20 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445(6 \u0446\u0438\u0444\u0440 \u0438\u043b\u0438 \u0431\u0443\u043a\u0432 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430) \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c 56 800 235 584 url-\u043e\u0432 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u0435.<\/p>\n<p><strong>unique=True<\/strong>, # \u0442\u0443\u0442 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 url \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c<\/p>\n<p><strong>db_index=True<\/strong>, # \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043b\u044e short_url<\/p>\n<p><strong>blank=True<\/strong> # \u043f\u043e\u043b\u0435 short_url \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u0430\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>requests_count<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>requests_count<\/strong> \u2013 \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>created_date<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>created_date<\/strong> &#8212; \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u0434\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u043d\u0435\u0439 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043d\u043e \u043c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0435\u0448\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0441\u0441\u044b\u043b\u043a\u0438 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u043d\u0430\u0442\u044c \u0434\u0430\u0442\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>is_active<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>is_active<\/strong> \u2013 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0438\u043b\u0438 \u043d\u0435\u0442. \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f True \u0438\u043b\u0438 False.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0435\u0442\u043e\u0434 save. <\/p>\n<pre><code class=\"python\">def save(self, *args, **kwargs):         \"\"\"         \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438,         \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.         \u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0442\u043e\u043a\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c         \"\"\"         if not self.short_url:             while True:  # \u0446\u0438\u043a\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443                 self.short_url = ''.join(                     random.choices(                         settings.CHARACTERS,  # \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a                         k=settings.TOKEN_LENGTH  # \u0434\u043b\u0438\u043d\u0443 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0442\u043e\u0436\u0435                     )                 )                 if not Tokens.objects.filter(  # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c                     short_url=self.short_url                 ).exists():                     break         super().save(*args, **kwargs)<\/code><\/pre>\n<p>\u041e\u043d \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043b \u0435\u0435 \u0432 \u0442\u0435\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.\u00a0<\/p>\n<p>\u0421 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0432\u0440\u043e\u0434\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0432 \u0444\u0430\u0439\u043b <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a>. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b <a href=\"http:\/\/settings.py\" rel=\"noopener noreferrer nofollow\">settings.py<\/a> \u0438 \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0433\u0434\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u043d\u0438\u0437\u0443:<\/p>\n<pre><code class=\"python\"># \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0422\u043e\u043a\u0435\u043d\u0430(\u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438) CHARACTERS = 'ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz234567890' TOKEN_LENGTH = 6<\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438. \u0413\u043e\u0442\u043e\u0432\u043e.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0438<\/h3>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0430\u043d\u0435\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e Django \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0443\u0440\u043b\u0430 <code>admin\/<\/code>, \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430\u0441\u044c \u043d\u0430\u0448\u0430 \u0430\u0434\u043c\u0438\u043d\u043a\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b admin.py \u0432 \u043f\u0430\u043f\u043a\u0435 api \u0438 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"python\">from django.contrib import admin  from .models import Tokens  # \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c Tokens   @admin.register(Tokens) class TokenAdmin(admin.ModelAdmin):     \"\"\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0438 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0422\u043e\u043a\u0435\u043d\u043e\u0432\"\"\"     list_display = (  # \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0435\u0439         'full_url',         'short_url',         'requests_count',         'created_date',         'is_active'     )     search_fields = ('full_url', 'short_url')  # \u043f\u043e\u043b\u044f \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d     ordering = ('-created_date',)  # \u0432\u0441\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0431\u044b\u043b\u0438 \u0441\u0432\u0435\u0440\u0445\u0443<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a \u043a\u043e\u0434\u0443. <\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438. \u0418\u0437 \u043f\u0430\u043f\u043a\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c manage.py \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p><code>python manage.py makemigrations<\/code><\/p>\n<p><code>python manage.py migrate<\/code><\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u0411\u0414 \u0441\u043e\u0437\u0434\u0430\u043d\u0430, \u0430\u0434\u043c\u0438\u043d\u043a\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0443\u043f\u0435\u0440\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0443:<\/p>\n<p>\u0418\u0437 \u043f\u0430\u043f\u043a\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c manage.py \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p><code>python manage.py createsuperuser<\/code><\/p>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (username, email, password)<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<p><code>python manage.py runserver<\/code><\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 <a href=\"http:\/\/127.0.0.1:8000\/admin\/\" rel=\"noopener noreferrer nofollow\">http:\/\/127.0.0.1:8000\/admin\/<\/a><\/p>\n<p>\u0412\u0443\u0430\u043b\u044f.<\/p>\n<h2>TTD (Test-Driven Development)<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u043a\u0430\u043a \u0435\u0432\u0430\u043d\u0433\u0435\u043b\u0438\u0441\u0442 TTD (Test-Driven Development) \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0447\u0442\u043e \u0436\u0435 \u043c\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 <\/p>\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-394175","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/394175","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=394175"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/394175\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=394175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=394175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=394175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}