diff --git a/feedler/models/admin.py b/feedler/models/admin.py index 5d1cd1d..c6b6587 100644 --- a/feedler/models/admin.py +++ b/feedler/models/admin.py @@ -1,11 +1,4 @@ # -*- coding: utf-8 -*- -from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse -from django.utils.decorators import method_decorator -from django.utils.functional import cached_property -from django.utils.translation import ugettext as _ -from wagtail.contrib.modeladmin.helpers import AdminURLHelper, ButtonHelper -from wagtail.contrib.modeladmin.views import IndexView import requests, json, codecs @@ -72,129 +65,3 @@ def handle_save_settings(sender, instance, *args, **kwargs): entry = feedparser.parse(entry, raw_entry, stream) # Persist resulting object entry.save() - -class ExportButtonHelper(ButtonHelper): - """ - This helper constructs all the necessary attributes to create a button. - - There is a lot of boilerplate just for the classnames to be right :( - """ - - export_button_classnames = ['icon', 'icon-download'] - - def export_button(self, classnames_add=None, classnames_exclude=None): - if classnames_add is None: - classnames_add = [] - if classnames_exclude is None: - classnames_exclude = [] - - classnames = self.export_button_classnames + classnames_add - cn = self.finalise_classname(classnames, classnames_exclude) - text = _('Export {}'.format(self.verbose_name_plural.title())) - - return { - 'url': self.url_helper.get_action_url('export', query_params=self.request.GET), - 'label': text, - 'classname': cn, - 'title': text, - } - - -class ExportAdminURLHelper(AdminURLHelper): - """ - This helper constructs the different urls. - - This is mostly just to overwrite the default behaviour - which consider any action other than 'create', 'choose_parent' and 'index' - as `object specific` and will try to add the object PK to the url - which is not what we want for the `export` option. - - In addition, it appends the filters to the action. - """ - - non_object_specific_actions = ('create', 'choose_parent', 'index', 'export') - - def get_action_url(self, action, *args, **kwargs): - query_params = kwargs.pop('query_params', None) - - url_name = self.get_action_url_name(action) - if action in self.non_object_specific_actions: - url = reverse(url_name) - else: - url = reverse(url_name, args=args, kwargs=kwargs) - - if query_params: - url += '?{params}'.format(params=query_params.urlencode()) - - return url - - def get_action_url_pattern(self, action): - if action in self.non_object_specific_actions: - return self._get_action_url_pattern(action) - - return self._get_object_specific_action_url_pattern(action) - - -class ExportView(IndexView): - """ - A Class Based View which will generate - """ - - def export_csv(self): - data = self.queryset.all() - data_headings = [field.verbose_name for field - in EventRegistration._meta.get_fields()] - - # return a CSV instead - response = HttpResponse(content_type='text/csv; charset=utf-8') - response['Content-Disposition'] = 'attachment;filename=' + \ - 'registrations.csv' - - # Prevents UnicodeEncodeError for labels with non-ansi symbols - data_headings = [smart_str(label) for label in data_headings] - - writer = csv.writer(response) - writer.writerow(data_headings) - for reg in data: - data_row = [] - data_row.extend([ - reg.title, reg.example_field2, reg.example_field3 - ]) - writer.writerow(data_row) - - return response - - - @method_decorator(login_required) - def dispatch(self, request, *args, **kwargs): - super().dispatch(request, *args, **kwargs) - return self.export_csv() - - -class ExportModelAdminMixin(object): - """ - A mixin to add to your model admin which hooks the different helpers, the view - and register the new urls. - """ - - button_helper_class = ExportButtonHelper - url_helper_class = ExportAdminURLHelper - - export_view_class = ExportView - - def get_admin_urls_for_registration(self): - urls = super().get_admin_urls_for_registration() - urls += ( - url( - self.url_helper.get_action_url_pattern('export'), - self.export_view, - name=self.url_helper.get_action_url_name('export') - ), - ) - - return urls - - def export_view(self, request): - kwargs = {'model_admin': self} - view_class = self.export_view_class - return view_class.as_view(**kwargs)(request) diff --git a/feedler/models/models.py b/feedler/models/models.py index 0aeb4cc..2ed0395 100644 --- a/feedler/models/models.py +++ b/feedler/models/models.py @@ -54,6 +54,118 @@ class Entry(models.Model): class Meta: verbose_name_plural = 'Entries' +# Button +class ExportButtonHelper(ButtonHelper): + """ + This helper constructs all the necessary attributes to create a button. + + There is a lot of boilerplate just for the classnames to be right :( + """ + + export_button_classnames = ['icon', 'icon-download'] + + def export_button(self, classnames_add=None, classnames_exclude=None): + if classnames_add is None: + classnames_add = [] + if classnames_exclude is None: + classnames_exclude = [] + + classnames = self.export_button_classnames + classnames_add + cn = self.finalise_classname(classnames, classnames_exclude) + text = _('Export {}'.format(self.verbose_name_plural.title())) + + return { + 'url': self.url_helper.get_action_url('export', query_params=self.request.GET), + 'label': text, + 'classname': cn, + 'title': text, + } + + +class ExportAdminURLHelper(AdminURLHelper): + """ + This helper constructs the different urls. + + This is mostly just to overwrite the default behaviour + which consider any action other than 'create', 'choose_parent' and 'index' + as `object specific` and will try to add the object PK to the url + which is not what we want for the `export` option. + + In addition, it appends the filters to the action. + """ + + non_object_specific_actions = ('create', 'choose_parent', 'index', 'export') + + def get_action_url(self, action, *args, **kwargs): + query_params = kwargs.pop('query_params', None) + + url_name = self.get_action_url_name(action) + if action in self.non_object_specific_actions: + url = reverse(url_name) + else: + url = reverse(url_name, args=args, kwargs=kwargs) + + if query_params: + url += '?{params}'.format(params=query_params.urlencode()) + + return url + + def get_action_url_pattern(self, action): + if action in self.non_object_specific_actions: + return self._get_action_url_pattern(action) + + return self._get_object_specific_action_url_pattern(action) + + +class ExportView(IndexView): + """ + A Class Based View which will generate + """ + + def export_csv(self): + data = self.queryset.all() + response = ... + return response + + + @method_decorator(login_required) + def dispatch(self, request, *args, **kwargs): + super().dispatch(request, *args, **kwargs) + return self.export_csv() + + +class ExportModelAdminMixin(object): + """ + A mixin to add to your model admin which hooks the different helpers, the view + and register the new urls. + """ + + button_helper_class = ExportButtonHelper + url_helper_class = ExportAdminURLHelper + + export_view_class = ExportView + + def get_admin_urls_for_registration(self): + urls = super().get_admin_urls_for_registration() + urls += ( + url( + self.url_helper.get_action_url_pattern('export'), + self.export_view, + name=self.url_helper.get_action_url_name('export') + ), + ) + + return urls + + def export_view(self, request): + kwargs = {'model_admin': self} + view_class = self.export_view_class + return view_class.as_view(**kwargs)(request) + + +class MenuModelAdmin(ExportModelAdminMixin, ModelAdmin): + model = Entry + class FeedPage(Page): intro = RichTextField(default='', blank=True) stream = models.ForeignKey(Stream, on_delete=models.PROTECT, diff --git a/feedler/templates/modeladmin/feedler/entry/index.html b/feedler/templates/modeladmin/feedler/entry/index.html deleted file mode 100644 index eed6636..0000000 --- a/feedler/templates/modeladmin/feedler/entry/index.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "modeladmin/index.html %} - -{% block header_extra %} - My New Button - {{ block.super }}{% comment %}Display the original buttons {% endcomment %} - {% include 'modeladmin/includes/button.html' with button=view.button_helper.export_button %} -{% endblock %} diff --git a/feedler/wagtail_hooks.py b/feedler/wagtail_hooks.py index afd2b14..ed8abd5 100644 --- a/feedler/wagtail_hooks.py +++ b/feedler/wagtail_hooks.py @@ -4,7 +4,6 @@ from wagtail.contrib.modeladmin.options import ( ModelAdmin, modeladmin_register) from .models import Entry, Stream -from .models.admin import ExportModelAdminMixin class EntryModelAdmin(ModelAdmin): model = Entry @@ -27,9 +26,3 @@ class StreamModelAdmin(ModelAdmin): list_display = ('title', 'ident') modeladmin_register(StreamModelAdmin) - -class EntryModelAdmin(ExportModelAdminMixin, ModelAdmin): - model = Entry - index_template_name = 'templates/modeladmin/feedler/entry/index.html' - -modeladmin_register(EntryModelAdmin) diff --git a/modeladmin/feedler/entry/index.html b/modeladmin/feedler/entry/index.html new file mode 100644 index 0000000..09a3d40 --- /dev/null +++ b/modeladmin/feedler/entry/index.html @@ -0,0 +1,11 @@ +{% extends "modeladmin/index.html %} + +{% block header_extra %} + {% if user_can_create %} +