8 февраля 2016 г.

dlango: autocomplete_light дополнительный рендер в json

Если цель - просто изменить рендер не в готовый html (для родных виджетов приложения), а в другой вид, в том числе json, то всё просто. Здесь же речь о том, чтобы добавить просто новый способ параллельно с полноценно работающим web-способом. В итоге будет и точно так же работающие автодополнения, рендерящие не в html, а в json, и индексная справка по корню, с корректными новыми url, указывающими на наши новые методы из api.

urls.py
from autocomplete_light.views import RegistryView
...
url(r'^api/autocomplete/(?P[-\w]+)/$', views.ApiAutocompleteView.as_view(), name='api_autocomplete_light_autocomplete'),
url(r'^api/autocomplete/$', RegistryView.as_view(template_name='autocomplete_light/api_registry.html'), name='api_autocomplete_light_registry'),
...

Вторая задача (вывод списка зарегистрированных автодополнений) решается вообще без переопределения, используем стандартную RegistryView, которая вполне подходит, нужно только переопределить template_name и в новом шаблоне вызвать get_absolute_url_api вместо get_absolute_url.

api_registry.html
{% if registry|length %}
    

List of your {{ registry_items|length }} registered api-autocompletes

{% for name, autocomplete in registry_items %} {% endfor %}

{{ name }}

{{ autocomplete.get_absolute_url_api }}
{% else %}

You have not registered any api-autocomplete

{% endif %}

Для всех autocomplete из registry приложения добавим новый миксин, который и содержит этот метод:

class AutocompleteApiMixin(object):
    def get_absolute_url_api(self):
        # NoReverseMatch не будем обрабатывать для простоты
        return urlresolvers.reverse('mysite:api_autocomplete_light_autocomplete', args=(self.__class__.__name__,))

и добавим во все модельки (autocomplete_light_registry.py)
class UserAutocomplete(AutocompleteApiMixin, autocomplete_light.AutocompleteModelBase):
    search_fields = ['username', 'first_name', 'last_name']
    model = MyUser
autocomplete_light.register(UserAutocomplete)

Первая же задача (собственно, автодополнение) решается либо написанием некоего ApiAutocompleteView по мотивам родного (см. в примере в urls.py выше):

class ApiAutocompleteView(GetRegistryMixin, generic.View):
    def get(self, request, *args, **kwargs):
        try:
            autocomplete_class = self.get_registry()[kwargs['autocomplete']]
        except AutocompleteNotRegistered:
            return HttpResponseBadRequest()
        autocomplete = autocomplete_class(request=request)
        # далее вместо autocomplete.autocomplete_html() используем autocomplete.choices_for_request()
 # и делаем с ним что хотим - рендерим в json, например...
 return HttpResponse(...)

Либо в одном из вариантов я делал так: вообще ничего не переопределял, а перегрузил в вышеупомянутом миксине AutocompleteApiMixin метод autocomplete_html, который рендерил в нужный мне вид в зависимости от условий (но для этого у меня удачно оказалось в request пропертис is_api, по которому я определял отдавать родной выход или рендерить кастомно), например, так:

class AutocompleteApiMixin(object):
...
    def autocomplete_html(self):
        if not self.request.is_api:
            return super(AutocompleteApiMixin, self).autocomplete_html()
        # здесь делаем по другому

Комментариев нет:

Отправить комментарий