{"id":228411,"date":"2014-07-02T16:01:03","date_gmt":"2014-07-02T12:01:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=228411"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=228411","title":{"rendered":"<span class=\"post_title\">Django widgets \u0438 \u0435\u0449\u0435 \u043f\u0430\u0440\u0430 \u0442\u0440\u044e\u043a\u043e\u0432<\/span>"},"content":{"rendered":"<div class=\"content html_format\">     \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/3bf\/3a2\/567\/3bf3a256702850a7fb4b0217f4b5dbf9.jpg\"\/><\/p>\n<p>  \u0412\u0441\u0435 \u0437\u043d\u0430\u044e\u0442 \u0447\u0442\u043e Django \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0441 \u043a\u0443\u0447\u0435\u0439 \u043c\u043e\u0449\u043d\u044b\u0445 \u0431\u0430\u0442\u0430\u0440\u0435\u0435\u043a. \u041b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f, \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 django \u0432\u0441\u0435 \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u2014 \u0432\u0441\u0435 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0434\u0443\u043c\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u0435. \u041d\u043e \u0442\u0435 \u043a\u0442\u043e \u0441 \u043d\u0438\u043c \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u043e\u0447\u043d\u043e, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u0443. \u0428\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u044c\u044e\u0448\u043a\u0438 \u0441\u0442\u0430\u043b\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0430 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u043e\u0441\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0438 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041d\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0435\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430, \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u044b\u043b \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439, \u0438, \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0447\u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0438\u043c\u0435\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043a\u0430\u043a \u0432 cms, \u0438, \u0432\u0440\u043e\u0434\u0435 \u0431\u044b, \u0435\u0441\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 django cms, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0432\u0441\u0435\u0433\u043e \u0438 \u043d\u0430\u0434\u043e \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041d\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0430\u0440\u0443 \u0444\u0438\u0447 \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<a name=\"habracut\"><\/a><habracut\/><br \/>  \u0412 \u044d\u0442\u043e\u0439 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0432\u044b \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0440\u0435\u0446\u0435\u043f\u0442\u043e\u0432, \u0446\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c\u0438 \u0437\u0430\u0434\u0443\u043c\u043a\u0430\u043c\u0438. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 \u0441\u043b\u0443\u0436\u0430\u0442 \u043b\u0438\u0448\u044c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043c\u043e\u0447\u044c \u0432 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0431\u0435\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043e\u043a \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430. \u041d\u043e \u0435\u0441\u043b\u0438 \u0442\u0435\u043c\u0430 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0418\u043b\u0438 \u0434\u0430\u0436\u0435 \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441.<\/p>\n<h4>\u041c\u043e\u0434\u0435\u043b\u0438<\/h4>\n<p>  \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 2 \u043c\u043e\u0434\u0435\u043b\u0438 \u0441 \u043e\u0431\u0449\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438: \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0442\u0435\u0433\u0438. \u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0432 \u043b\u0435\u043d\u0442\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u0438\u0437 \u043e\u0431\u043e\u0438\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u0445 \u0432 \u043e\u0434\u043d\u0443 \u043c\u043e\u0434\u0435\u043b\u044c. \u0410 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u043e\u043d\u0438 \u043d\u0435 \u0441\u043b\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0432 \u043e\u0434\u043d\u0443 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/docs.djangoproject.com\/en\/dev\/ref\/contrib\/contenttypes\/#django.contrib.contenttypes.fields.GenericForeignKey\">Generic Foreign Key<\/a>.<br \/>  \u0414\u043b\u044f \u0430\u0434\u043c\u0438\u043d\u043a\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c inline \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Info \u0438 \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c <a href=\"https:\/\/djangosnippets.org\/snippets\/1773\/\">GFKManager<\/a> \u2014 \u0441\u043d\u0438\u043f\u043f\u0435\u0442 \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"python\">from django.db import models from core.container.manager import GFKManager  class Info(models.Model):     objects = GFKManager()      title = models.CharField(         max_length=256, blank=True, null=True     )     header = models.TextField(         max_length=500, blank=True, null=True     )     tags = models.ManyToManyField(         'self', symmetrical=False, blank=True, null=True     )     def content_type_name(self):         return self.content_type.model_class()._meta.verbose_name  class Model(models.Model):     info = CustomGenericRelation(         'Info',         related_name=&quot;%(class)s_info&quot;     )  class A(Model):     field = models.CharField(         max_length=256, blank=True, null=True     )  class B(Model):     pass <\/code><\/pre>\n<p>  \u0418\u043c\u0435\u0439\u0442\u0435 \u0432\u0432\u0438\u0434\u0443 \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 A \u0438 B, \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c generic.GenericRelation. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043d\u0435 \u043c\u043e\u0433\u0443 \u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0432\u043e\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a:  <\/p>\n<pre><code class=\"python\"># -*- coding: utf-8 -*- from django.contrib.contenttypes import generic from django.db.models.related import RelatedObject from south.modelsinspector import add_introspection_rules   class CustomGenericRelation(generic.GenericRelation):     def contribute_to_related_class(self, cls, related):         super(CustomGenericRelation, self).contribute_to_related_class(cls, related)         if self.rel.related_name and not hasattr(self.model, self.rel.related_name):             rel_obj = RelatedObject(cls, self.model, self.rel.related_name)             setattr(cls, self.rel.related_name, rel_obj)   add_introspection_rules([     (         [CustomGenericRelation],         [],         {},     ), ], [&quot;^core\\.ext\\.fields\\.generic\\.CustomGenericRelation&quot;]) <\/code><\/pre>\n<p>  \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441:  <\/p>\n<pre><code class=\"python\">Info.objects.filter(content_type__in=(CT.models.A, CT.models.B)) <\/code><\/pre>\n<p>  \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043a\u0430\u0440\u0442\u0443 ContentType:  <\/p>\n<pre><code class=\"python\">rom django.contrib.contenttypes.models import ContentType from django.db import models from models import Model  class Inner(object):     def __get__(self, name):         return getattr(self.name)   class ContentTypeMap(object):     __raw__ = {}      def __get__(self, obj, addr):         path = addr.pop(0)         if not hasattr(obj, path):             setattr(obj, path, type(path, (object,), {'parent': obj}))         attr = getattr(obj, path)         return self.__get__(attr, addr) if addr else attr      def __init__(self):         for model in filter(lambda X: issubclass(X, Model), models.get_models()):             content_type = ContentType.objects.get_for_model(model)             obj = self.__get__(self, model.__module__.split('.'))             self.__raw__[content_type.model] = content_type.id             setattr(obj, '%s' % model.__name__, content_type)         for obj in map(lambda X: self.__get__(self, X.__module__.split('.')),             filter(lambda X: issubclass(X, Model), models.get_models())):             setattr(obj.parent, obj.__name__, obj())   CT = ContentTypeMap() <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0438\u0441\u043a (sphinx) \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c django-sphinx \u043a Info. \u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0434\u043d\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u0435\u043d\u0442\u0443, \u043f\u043e\u0438\u0441\u043a, \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u043f\u043e \u0442\u0435\u0433\u0430\u043c \u0438 \u0442\u0434. \u041c\u0438\u043d\u0443\u0441 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 Info, \u0430 \u0432 \u0441\u0430\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0444\u0438\u043b\u044c\u0442\u0440 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438.<\/p>\n<h4>Django CMS, \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u044b<\/h4>\n<p>  \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 CMS \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0438\u0434\u0436\u0435\u0442\u044b, \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u0439\u0434\u0431\u0430\u0440\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435, \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u043c\u0430\u043d\u0435\u043d\u0442\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d \u0432 \u0448\u0430\u0431\u043b\u043e\u043d, \u0442\u0430\u043a \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0431\u044b\u043b \u0432\u0438\u0434\u0435\u043d \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445. <a href=\"https:\/\/github.com\/smyrman\/django-jquery-widgets\">django widgets<\/a> \u2014 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0442\u0435\u0433\u0430 include_widget \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0438 \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e. \u0415\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c ajax&#8217;\u043e\u043c \u043a\u0430\u043a\u0438\u0435 \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u043b\u0430\u0433\u0438\u043d. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <a href=\"https:\/\/django-tastypie.readthedocs.org\/en\/latest\/\">tastypie<\/a>.<\/p>\n<pre><code class=\"python\">from django.conf.urls.defaults import * from django.http import HttpResponseForbidden from django_widgets.loading import registry from sekizai.context import SekizaiContext from tastypie.resources import Resource from tastypie.utils import trailing_slash from tastypie.serializers import Serializer from core.widgets.cms_plugins import PLUGIN_TEMPLATE_MAP from core.ext.decorator import api_require_request_parameters   class HtmlSreializer(Serializer):     def to_html(self, data, options=None):         return data   class WidgetResource(Resource):     class Meta:         resource_name = 'widget'         include_resource_uri = False         serializer = HtmlSreializer(formats=['html'])      def prepend_urls(self):         return [             url(r&quot;^(?P&lt;resource_name&gt;%s)\/render%s$&quot; % (self._meta.resource_name, trailing_slash()), self.wrap_view('render'), name=&quot;api_render&quot;)         ]      @api_require_request_parameters(['template'])     def render(self, request, **kwargs):         data = dict(request.GET)         template = data.pop('template')[0]         if 'widget' in data:             widget = registry.get(data.pop('widget')[0])         else:             if template not in PLUGIN_TEMPLATE_MAP:                 return  HttpResponseForbidden()             widget = PLUGIN_TEMPLATE_MAP[template]          data = dict(map(lambda (K, V): (K.rstrip('[]'), V) if K.endswith('[]') else (K.rstrip('[]'), V[0]), data.items()))         return self.create_response(             request,             widget.render(SekizaiContext({'request': request}), template, data, relative_template_path=False)         )      def obj_get_list(self, bundle, **kwargs):         return [] <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0434\u0430\u0432 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0435\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442. \u0422\u0443\u0442 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e PLUGIN_TEMPLATE_MAP \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430.<\/p>\n<p>  \u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u0422\u0443\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u0443\u0441\u043e\u043a, \u043d\u043e \u0441\u0430\u043c\u044b\u0439 \u0432\u0430\u0436\u043d\u044b\u0439.   <\/p>\n<pre><code class=\"python\">import os import json from django import forms from django.conf import settings from django_widgets.loading import registry from cms.models import CMSPlugin from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool from core.widgets.widgets import ItemWidget   PLUGIN_MAP = {} PLUGIN_CT_MAP = {} PLUGIN_TEMPLATE_MAP = {}   class PluginWrapper(CMSPluginBase):     admin_preview = False  class FormWrapper(forms.ModelForm):     widget = None     templates_available = ()      def __init__(self, *args, **kwargs):         super(FormWrapper, self).__init__(*args, **kwargs)         if not self.fields['template'].initial:             # TODO             self.fields['template'].initial = self.widget.default_template             self.fields['template'].help_text = 'at PROJECT_ROOT\/templates\/%s' % self.widget.get_template_folder()              if self.templates_available:                 self.fields['template'].widget = forms.Select()                 self.fields['template'].widget.choices = self.templates_available           self.__extra_fields__ = set(self.fields.keys()) - set(self._meta.model._meta.get_all_field_names())          data = json.loads(self.instance.data or '{}') if self.instance else {}         for key, value in data.items():             self.fields[key].initial = value      def clean(self):         cleaned_data = super(FormWrapper, self).clean()         cleaned_data['data'] = json.dumps(dict(             map(                 lambda K: (K, cleaned_data[K]),                 filter(                     lambda K: K in cleaned_data,                     self.__extra_fields__                 )             )         ))          return cleaned_data      class Meta:         model = CMSPlugin         widgets = {             'data': forms.HiddenInput()         }   def get_templates_available(widget):     template_folder = widget.get_template_folder()     real_folder = os.path.join(settings.TEMPLATE_DIRS[0], *template_folder.split('\/'))     result = ()      if os.path.exists(real_folder):         for path, dirs, files in os.walk(real_folder):             if path == real_folder:                 choices = filter(lambda filename: filename.endswith('html'), files)                 result = zip(choices, choices)             rel_folder =  '%(template_folder)s%(inner_path)s' % {                 'template_folder': template_folder,                 'inner_path': path.replace(real_folder, '')             }             for filename in files:                 PLUGIN_TEMPLATE_MAP['\/'.join((rel_folder, filename))] = widget     return result   def register_plugin(widget, plugin):     plugin_pool.register_plugin(plugin)     PLUGIN_MAP[widget.__class__] = plugin      if issubclass(widget.__class__, ItemWidget):         for content_type in widget.__class__.content_types:             if content_type not in PLUGIN_CT_MAP:                 PLUGIN_CT_MAP[content_type] = []             PLUGIN_CT_MAP[content_type].append(plugin)  def get_plugin_form(widget, widget_name):     return type('FormFor%s' % widget_name, (FormWrapper,), dict(map(         lambda (key, options): (key, (options.pop('field') if 'field' in options else forms.CharField)(initial=getattr(widget, key, None), **options)),         getattr(widget, 'kwargs', {}).items()     ) + [('widget', widget), ('templates_available', get_templates_available(widget))]))  def register_plugins(widgets):     for widget_name, widget in widgets:         if getattr(widget, 'registered', False):             continue         name = 'PluginFor%s' % widget_name         plugin = type(             name, (PluginWrapper,),             {                 'name': getattr(widget, 'name', widget_name),                 'widget': widget,                 'form': get_plugin_form(widget, widget_name)             }         )         register_plugin(widget, plugin)  register_plugins(registry.widgets.items()) <\/code><\/pre>\n<h4>\u0415\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432\u043a\u0443\u0441\u043d\u044b\u0445 \u0431\u0430\u0442\u0430\u0440\u0435\u0435\u043a<\/h4>\n<p>  <\/p>\n<ul>\n<li><a href=\"http:\/\/django-sekizai.readthedocs.org\/en\/latest\/\">django-sekizai<\/a> \u2014 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c django cms, \u043d\u043e, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0431\u0435\u0437 \u043d\u0435\u0433\u043e<\/li>\n<li><a href=\"https:\/\/readthedocs.org\/projects\/django-localeurl\/\">django-localeurl<\/a> \u2014 \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u0448\u0442\u0443\u043a\u0438 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430<\/li>\n<li><a href=\"https:\/\/github.com\/deschler\/django-modeltranslation\">django-modeltranslation<\/a> \u2014 \u043a\u0430\u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043d\u043e \u0435\u0441\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0432\u043a\u0443\u0441\u043d\u044b\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b<\/li>\n<li><a href=\"https:\/\/github.com\/sebleier\/django-redis-cache\">django-redis-cache<\/a> \u2014 \u043a\u0435\u0448 \u0432 \u0440\u0435\u0434\u0438\u0441\u0435, \u0442\u0443\u0434\u0430 \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0441\u0443\u043d\u0443\u0442\u044c \u0438 \u0441\u0435\u0441\u0441\u0438\u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0433\u043e\u0434\u0430\u043c\u0438 \u043d\u0435 \u0447\u0438\u0441\u0442\u0438\u0442\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438\u0437 MySQL<\/li>\n<li><a href=\"https:\/\/github.com\/django-admin-bootstrapped\/django-admin-bootstrapped\">django-admin-bootstrapped<\/a> \u2014 \u0431\u043e\u043b\u0435\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0430\u0434\u043c\u0438\u043d\u043a\u0430, (\u043d\u0430\u0434\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c bootstrap-modeltranslation \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 modeltranslation )<\/li>\n<li><a href=\"https:\/\/github.com\/NElias\/django-sorl-cropping\">django-sorl-cropping<\/a> \u2014 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 thumbnail<\/li>\n<\/ul>\n<p>  \u041d\u0443 \u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0435\u0449\u0438:  <\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/omab\/django-social-auth\">django-social-auth<\/a><\/li>\n<li><a href=\"http:\/\/django-registration.readthedocs.org\/en\/latest\/\">django-registration<\/a><\/li>\n<li><a href=\"http:\/\/django-debug-toolbar.readthedocs.org\/en\/1.2\/\">django-debug-toolbar<\/a><\/li>\n<li><a href=\"https:\/\/bitbucket.org\/izi\/django-admin-tools\/wiki\/Home\">django-admin-tools<\/a><\/li>\n<\/ul>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0434\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 django, \u0445\u043e\u0442\u0435\u043b \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u043d\u043e \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043e\u0431\u044a\u0435\u043c\u043d\u043e\u0439. \u0414\u0440\u0443\u0433\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u044d\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0443\u0440\u043b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u2014 \u0432\u0438\u0434\u0436\u0435\u0442 \u043b\u0435\u043d\u0442\u044b \u0438 \u0432\u0438\u0434\u0436\u0435\u0442 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u044d\u0442\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437. \u0418\u0442\u0430\u043a, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430 \u044f  <\/p>\n<ul>\n<li> \u0441\u043e\u0437\u0434\u0430\u044e \u043d\u043e\u0432\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u0438\u0445 \u0432 \u043b\u0435\u043d\u0442\u0443 \u0437\u0430 \u043f\u0430\u0440\u0443 \u043c\u0438\u043d\u0443\u0442 (\u043a\u043e\u0433\u0434\u0430 \u0442\u0430\u043a\u0438\u0445 \u043b\u0435\u043d\u0442 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043e\u043a\u043e\u043b\u043e 50 \u044d\u0442\u043e \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435);<\/li>\n<li> \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0438\u0448\u0443 \u0432\u044c\u044e\u0448\u043a\u0438, \u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e \u0432\u0438\u0434\u0436\u0435\u0442\u044b, \u0438\u0437\u0440\u0435\u0434\u043a\u0430 \u043f\u0438\u0448\u0443 \u043d\u043e\u0432\u044b\u0435;<\/li>\n<li> \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u044e \u043d\u043e\u0432\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f url, \u0437\u0430 \u043c\u0435\u043d\u044f \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 django cms;<\/li>\n<li> \u043d\u0435 \u043f\u0430\u0440\u044e\u0441\u044c \u0441 ajax, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442;<\/li>\n<li> \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u043b \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c, \u043d\u0430 \u0442\u0440\u0435\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0434\u0438\u043d \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439;<\/li>\n<li> \u0442\u0440\u0430\u0447\u0443 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 js \u0447\u0435\u043c \u043d\u0430 django, \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f.<\/li>\n<\/ul>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/company\/starttospeak\/blog\/228411\/\"> http:\/\/habrahabr.ru\/company\/starttospeak\/blog\/228411\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">     \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/3bf\/3a2\/567\/3bf3a256702850a7fb4b0217f4b5dbf9.jpg\"\/><\/p>\n<p>  \u0412\u0441\u0435 \u0437\u043d\u0430\u044e\u0442 \u0447\u0442\u043e Django \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0441 \u043a\u0443\u0447\u0435\u0439 \u043c\u043e\u0449\u043d\u044b\u0445 \u0431\u0430\u0442\u0430\u0440\u0435\u0435\u043a. \u041b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f, \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 django \u0432\u0441\u0435 \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u2014 \u0432\u0441\u0435 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0434\u0443\u043c\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u0435. \u041d\u043e \u0442\u0435 \u043a\u0442\u043e \u0441 \u043d\u0438\u043c \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u043e\u0447\u043d\u043e, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u0443. \u0428\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u044c\u044e\u0448\u043a\u0438 \u0441\u0442\u0430\u043b\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0430 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u043e\u0441\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0438 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041d\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0435\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430, \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u044b\u043b \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439, \u0438, \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0447\u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0438\u043c\u0435\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043a\u0430\u043a \u0432 cms, \u0438, \u0432\u0440\u043e\u0434\u0435 \u0431\u044b, \u0435\u0441\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 django cms, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0432\u0441\u0435\u0433\u043e \u0438 \u043d\u0430\u0434\u043e \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041d\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0430\u0440\u0443 \u0444\u0438\u0447 \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\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-228411","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/228411","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=228411"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/228411\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=228411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=228411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=228411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}