{"id":177929,"date":"2013-04-25T11:30:04","date_gmt":"2013-04-25T07:30:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=177929"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=177929","title":{"rendered":"<span class=\"post_title\">\u041f\u043e\u043b\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0432 Django<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t\u041f\u0440\u0438\u0432\u0435\u0442, \u0445\u0430\u0431\u0440.<br \/>  \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0432\u043e\u0435\u0439 <a href=\"http:\/\/habrahabr.ru\/post\/176807\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u043e\u043f\u0438\u0441\u0430\u043b \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u0433\u043e\u0432 \u0432 Django. \u0421\u0435\u0439\u0447\u0430\u0441 \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u043c \u0438 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043f\u043e AJAX. \u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043e\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430, \u043d\u043e \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435. \u0417\u0430 front-end \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 jQuery-\u043f\u043b\u0430\u0433\u0438\u043d <a href=\"http:\/\/ivaynberg.github.io\/select2\/\">Select2<\/a>. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043e \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Django.<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u0412\u0438\u0434\u0436\u0435\u0442<\/h4>\n<p>  <\/p>\n<pre><code class=\"python\">from django.forms.widgets import Widget from django.conf import settings from django.utils.safestring import mark_safe from django.template.loader import render_to_string  class InfiniteChoiceWidget(Widget): '''Infinite choice widget, based on Select2 jQuery-plugin (http:\/\/ivaynberg.github.io\/select2\/)'''  \tclass Media: \t    js = ( \t        settings.STATIC_URL + &quot;select2\/select2.js&quot;, \t    ) \t    css = { \t        'all': (settings.STATIC_URL + 'select2\/select2.css',) \t    }  \tdef __init__(self, data_model, multiple=False, disabled=False, attrs=None): \t    super(InfiniteChoiceWidget, self).__init__(attrs) \t    self.data_model = data_model \t    self.multiple = multiple \t    self.disabled = disabled  \tdef render(self, name, value, attrs=None): \t    return mark_safe(render_to_string(&quot;infinite_choice_widget.html&quot;, \t                                      {&quot;disabled&quot;: self.disabled, \t                                       &quot;multiple&quot;: self.multiple, \t                                       &quot;attrs&quot;: attrs, \t                                       &quot;app_name&quot;: self.data_model._meta.app_label, \t                                       &quot;model_name&quot;: self.data_model.__name__, \t                                       &quot;input_name&quot;: name, \t                                       &quot;current_value&quot;: value if value else &quot;&quot;, \t                                       }) \t                     ) <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438, \u0444\u043b\u0430\u0433\u0438 multiple \u0438 disabled, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0437\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044f. \u0412 \u0441\u0443\u0431\u043a\u043b\u0430\u0441\u0441\u0435 Media \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u0441\u0442\u0438\u043b\u0438 Select2. \u0421\u043a\u0440\u0438\u043f\u0442, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u043b\u0430\u0433\u0438\u043d Select2, \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 infinite_choice_widget.html.  <\/p>\n<pre><code class=\"html\">{% load url from future %} {# \u0420\u0435\u0436\u0438\u043c \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 django 1.5 #}  &lt;input type=&quot;hidden&quot;        {% for key,value in attrs.iteritems %}            {{key}}=&quot;{{value}}&quot;        {% endfor %}        name=&quot;{{input_name}}&quot;        value=&quot;{{current_value}}&quot; \/&gt;  {# Settings for Select2 #} &lt;script type=&quot;text\/javascript&quot;&gt;     $(&quot;#{{attrs.id}}&quot;).select2({         multiple: {{multiple|yesno:&quot;true,false&quot;}},         formatInputTooShort: function (input, min) { return &quot;\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 &quot; + (min - input.length) + &quot; \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432&quot;; },         formatSearching: function () { return &quot;\u041f\u043e\u0438\u0441\u043a...&quot;; },         formatNoMatches: function () { return &quot;\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e&quot;; },         minimumInputLength: 3,         initSelection : function (element, callback) {             $.ajax({                 url: &quot;{% url 'infinite_choice_data' app_name model_name %}&quot;,                 type: 'GET',                 dataType: 'json',                 data: {ids: element.val()},                 success: function(data, textStatus, xhr) {                   callback(data);                 },                 error: function(xhr, textStatus, errorThrown) {                     callback({});                 }             });         },         ajax: {             url: &quot;{% url 'infinite_choice_data' app_name model_name %}&quot;,             dataType: 'json',             data: function (term, page) {             return {term: term, \/\/ search term                     page_limit: 10                 };             },             results: function (data, page) {                 return {results: data};             }         }     });      {% if disabled %}         $(&quot;#{{attrs.id}}&quot;).select2(&quot;disable&quot;);     {% endif %} &lt;\/script&gt;\t <\/code><\/pre>\n<p>  \u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0437\u0434\u0435\u0441\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043a\u0440\u044b\u0442\u044b\u0439 input, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432. \u0410 \u0443\u0436\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u043f\u043e #id \u043d\u0430\u0442\u0440\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u0433\u0438\u043d Select2.<br \/>  \u041f\u0440\u043e\u0431\u0435\u0436\u0438\u043c\u0441\u044f \u043f\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0430.   <\/p>\n<ul>\n<li><b>multiple<\/b> \u2014 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\/\u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430<\/li>\n<li><b>formatInputTooShort<\/b> \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0443\u044e, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432\u0432\u0435\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0434\u043e \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/li>\n<li><b>formatSearching<\/b> \u2014 \u0441\u0442\u0440\u043e\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f, \u0447\u0442\u043e \u0438\u0434\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0438\u0441\u043a\u0430<\/li>\n<li><b>formatNoMatches<\/b> \u2014 \u0441\u0442\u0440\u043e\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u043e\u0442 \u0431\u0435\u0437\u044b\u0441\u0445\u043e\u0434\u043d\u043e\u0441\u0442\u0438&#8230;<\/li>\n<li><b>minimumInputLength<\/b> \u2014 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0434\u043b\u044f \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/li>\n<li><b>initSelection<\/b> \u2014 \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u0441\u043a\u0440\u044b\u0442\u043e\u043c \u043f\u043e\u043b\u0435 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0442\u043e \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u0435\u043b\u0430\u0435\u0442 AJAX-\u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043d\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442 \u043f\u043e\u0438\u0441\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.<\/li>\n<li><b>ajax<\/b> \u2014 \u043e\u0442\u0441\u044b\u043b\u0430\u0435\u0442 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 {id: &#8230;, title: &#8230;}, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 title \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430. <b>term<\/b> \u2014 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0439, <b>page_limit<\/b> \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432.<\/li>\n<\/ul>\n<p>  \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 URL, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u043c\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0438\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f: \u0432\u044c\u044e\u0445\u0435 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0447\u0435\u0442\u043a\u043e \u0437\u043d\u0430\u0442\u044c, \u0438\u0437 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435, \u043c\u044b \u0435\u0439 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437.<br \/>  \u0412 \u043a\u043e\u043d\u0446\u0435 \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0443 \u0431\u044b\u0442\u044c \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c, \u0435\u0441\u043b\u0438 \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043b disabled=True.<\/p>\n<h4>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/h4>\n<p>  \u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u0432\u044c\u044e\u0445\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0435\u0439 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u043d\u0430\u0442\u044c, \u0438\u0437 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u0440\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. \u0415\u0441\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u043e\u0434\u0435\u043b\u0438, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0438\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u044d\u0442\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432\u043e \u0432\u044e\u0445\u0443.  <\/p>\n<pre><code class=\"python\">from django.http import Http404, HttpResponse import json from django.db.models import get_model   def infinite_choice_data(request, app_name, model_name):     '''Returns data for infinite choice field'''      data = []      if not request.is_ajax():         raise Http404      model = get_model(app_name, model_name)       if 'term' in request.GET:         term = request.GET['term']         page_limit = request.GET['page_limit']          data = model.objects.filter(title__startswith=term)[:int(page_limit)]          json_data = json.dumps([{&quot;id&quot;: item.id, &quot;text&quot;: unicode(item.title)} for item in data])      if 'ids' in request.GET:         id_list = request.GET['ids'].split(',')          items = model.objects.filter(pk__in=id_list)          json_data = json.dumps([{&quot;id&quot;: item.id, &quot;text&quot;: item.title} for item in items])      response = HttpResponse(json_data, content_type=&quot;application\/json&quot;)     response['Cache-Control'] = 'max-age=86400'     return response <\/code><\/pre>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u044f django.db.models.get_model \u0444\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438. \u0414\u0430\u043b\u0435\u0435, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043b\u0438\u0431\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0438 term, \u043b\u0438\u0431\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 id \u0440\u0430\u0432\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 ids. \u0412\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0441 \u0443\u0436\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. <br \/>  \u042f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0432 response \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Cache-Control, \u0441 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0436\u0438\u0437\u043d\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u044d\u0448\u0435 \u2014 \u0441\u0443\u0442\u043a\u0438. \u042d\u0442\u043e \u0447\u0442\u043e\u0431 \u043d\u0435 \u0434\u0435\u0440\u0433\u0430\u0442\u044c \u0431\u0430\u0437\u0443 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438. \u041e\u0447\u0435\u043d\u044c \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u044f \u0441 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u043c\u0438 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0442\u0438\u043f\u0430 \u041a\u041b\u0410\u0414\u0420\/\u0424\u0418\u0410\u0421.<\/p>\n<p>  \u0410 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 urls.py \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0432\u044c\u044e\u0445\u0438.  <\/p>\n<pre><code class=\"python\">from django.conf.urls import patterns, url from views import infinite_choice_data  urlpatterns = patterns('',                        url(r'^(?P&lt;app_name&gt;[\\w\\d_]+)\/(?P&lt;model_name&gt;[\\w\\d_]+)\/$',                            view=infinite_choice_data,                            name='infinite_choice_data'),                        ) <\/code><\/pre>\n<h4>\u041f\u043e\u043b\u0435 \u0444\u043e\u0440\u043c\u044b<\/h4>\n<p>  \u041a\u0430\u043a \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u043f\u043e\u043b\u0435 \u0444\u043e\u0440\u043c\u044b \u0432 django \u0441\u043b\u0443\u0436\u0438\u0442, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0432 \u043d\u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<pre><code class=\"python\">from django.forms import fields as f_fields from django.core.exceptions import ValidationError from django.core import validators from django.utils.translation import ugettext_lazy as _  class InfiniteChoiceField(f_fields.Field):     '''Infinite choice field'''      default_error_messages = {         'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),     }      def __init__(self, data_model, multiple=False, disabled=False, widget_attrs=None, **kwargs):         self.data_model = data_model         self.disabled = disabled         self.multiple = multiple          widget = InfiniteChoiceWidget(data_model, multiple, disabled, widget_attrs)         super(InfiniteChoiceField, self).__init__(widget=widget, **kwargs)      def to_python(self, value):         if value in validators.EMPTY_VALUES:             return None          if self.multiple:             values = value.split(',')              qs = self.data_model.objects.filter(pk__in=values)             pks = set([i.pk for i in qs])              for val in values:                 if not int(val) in pks:                     raise ValidationError(self.error_messages['invalid_choice'] % {'value': val})              return qs         else:             try:                 return self.data_model.objects.get(pk=value)             except self.data_model.DoesNotExists:                 raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})      def prepare_value(self, value):          if value is not None and hasattr(value, '__iter__') and self.multiple:             return u','.join(unicode(v.pk) for v in value)         return unicode(value.pk) <\/code><\/pre>\n<p>  \u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 ModelMultipleChoiceField, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 queryset, \u0430 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e. <br \/>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u044e, \u0444\u043b\u0430\u0433\u0430\u043c\u0438 multiple \u0438 disabled \u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u043c\u0438 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438.<br \/>  \u041c\u0435\u0442\u043e\u0434 to_python \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 value \u043b\u0438\u0431\u043e \u043e\u0434\u0438\u043d\u043e\u0447\u043d\u044b\u0439 id, \u043b\u0438\u0431\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e id \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0444\u043b\u0430\u0433\u0430 multiple. \u0412 \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 id \u0432 \u043c\u043e\u0434\u0435\u043b\u0438.<br \/>  \u041c\u0435\u0442\u043e\u0434 prepare_value \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f: \u0435\u0441\u043b\u0438 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 initial \u043f\u043e\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u043e\u0434\u0438\u043d\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043c\u043e\u0434\u0435\u043b\u0438, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 id \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438; \u0435\u0441\u043b\u0438 \u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0438\u043b\u0438 QuerySet, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 id \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e.<\/p>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u041f\u043e\u043b\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044e. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c <a href=\"https:\/\/bitbucket.org\/pokidovea\/infinitechoicefield\/\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0435\u043c \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e:  <\/p>\n<pre><code class=\"python\">from django import forms from infinite_choice_field import InfiniteChoiceField from models import ChoiceModel  class TestForm(forms.Form):     choice = InfiniteChoiceField(ChoiceModel,                                  multiple=True,                                  disabled=False,                                  required=False,                                  initial=ChoiceModel.objects.filter(id__in=(7, 8, 12)))\t <\/code><\/pre>\n<p>  , \u0433\u0434\u0435 ChoiceModel \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u0438\u0434\u0430  <\/p>\n<pre><code class=\"python\">class ChoiceModel(models.Model):      title = models.CharField(max_length=100, verbose_name=&quot;Choice title&quot;)      class Meta:         verbose_name = 'ChoiceModel'         verbose_name_plural = 'ChoiceModels'      def __unicode__(self):         return self.title\t <\/code><\/pre>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 settings.py,   <\/p>\n<pre><code class=\"python\">INSTALLED_APPS = (     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.sites',     'django.contrib.messages',     'django.contrib.staticfiles',     'infinite_choice_field',     ... } <\/code><\/pre>\n<p>  \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c urls  <\/p>\n<pre><code class=\"python\">urlpatterns = patterns('',     # Examples:     # url(r'^$', 'habr_test.views.home', name='home'),     url(r'^', include('core.urls')),     url(r'^infinite_choice_data\/', include('infinite_choice_field.urls')),      # Uncomment the next line to enable the admin:     url(r'^admin\/', include(admin.site.urls)), ) <\/code><\/pre>\n<p>   \u0438 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u043a\u0443 \u0444\u043e\u0440\u043c\u044b TestForm \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435  <\/p>\n<pre><code class=\"html\">&lt;!doctype html&gt; &lt;html&gt;     &lt;head&gt;         &lt;title&gt;Test InfiniteChoiceField&lt;\/title&gt;         {{test_form.media}}     &lt;\/head&gt;     &lt;body&gt;         &lt;form action=&quot;&quot;&gt;             {{test_form}}             &lt;\/form&gt;     &lt;\/body&gt; &lt;\/html&gt;     <\/code><\/pre>\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\/post\/177929\/\"> http:\/\/habrahabr.ru\/post\/177929\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t\u041f\u0440\u0438\u0432\u0435\u0442, \u0445\u0430\u0431\u0440.<br \/>  \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0432\u043e\u0435\u0439 <a href=\"http:\/\/habrahabr.ru\/post\/176807\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u043e\u043f\u0438\u0441\u0430\u043b \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u0433\u043e\u0432 \u0432 Django. \u0421\u0435\u0439\u0447\u0430\u0441 \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u043c \u0438 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043f\u043e AJAX. \u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043e\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430, \u043d\u043e \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435. \u0417\u0430 front-end \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 jQuery-\u043f\u043b\u0430\u0433\u0438\u043d <a href=\"http:\/\/ivaynberg.github.io\/select2\/\">Select2<\/a>. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043e \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Django.  <\/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-177929","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/177929","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=177929"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/177929\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=177929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=177929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=177929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}