import json import requests from django.conf import settings from django.core.cache import cache from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.db import models from django.utils.translation import ugettext_lazy as _ from wagtail.admin.edit_handlers import FieldPanel from home.models import BasePage class ExternalSourceType(models.Model): name = models.CharField(max_length=200) slug = models.SlugField(max_length=200) panels = [ FieldPanel('name'), FieldPanel('slug'), ] class Meta: verbose_name = _("External source type") verbose_name_plural = _("External source types") def __str__(self): return self.name class ExternalSource(models.Model): name = models.CharField(max_length=200) error = models.TextField(null=True, blank=True) source_type = models.ForeignKey(ExternalSourceType, on_delete=models.PROTECT) api_url = models.URLField() api_key = models.CharField(max_length=500, null=True, blank=True) panels = [ FieldPanel('name'), FieldPanel('source_type'), FieldPanel('api_url'), FieldPanel('api_key'), ] class Meta: verbose_name = _("External source") verbose_name_plural = _("External sources") def __str__(self): return self.name def get_data(self): key = "{}{}-data-{}".format( settings.WAGTAIL_SITE_NAME, settings.WAGTAIL_EXTRA_SLUG, self.pk ) data = cache.get(key) if data: return data data = [] headers = {} base_error = str(_("Error while fetching the source:")) + " " if self.api_key: headers = {'Authorization': 'token {}'.format(self.api_key)} try: response = requests.get(self.api_url, headers=headers) if response.status_code == 401: self.error = base_error + str(_("permisssion denied - check " "your API key")) else: data = json.loads(response.text) cache.set(key, data) self.error = "" except json.JSONDecodeError: self.error = base_error + str(_("invalid source")) except requests.exceptions.Timeout: self.error = base_error + str(_("connection time out")) except requests.exceptions.TooManyRedirects: self.error = base_error + str(_("too many redirection")) except requests.exceptions.RequestException as e: self.error = base_error + str(_("unknown error")) + " - " + str(e) self.save() return data @property def data(self): return self.get_data() def get_item(self, item_number): if item_number >= len(self.data): return return self.data[item_number] class ShowCase(BasePage): external_source = models.ForeignKey(ExternalSource, on_delete=models.PROTECT) content_panels = [ FieldPanel('external_source') ] + BasePage.content_panels class Meta: verbose_name = _("Show case") verbose_name_plural = _("Show cases") @property def data(self): return self.external_source.get_data() def get_context(self, request): context = super(ShowCase, self).get_context(request) page = request.GET.get('page', 1) paginator = Paginator(self.data, 10) try: paginated_data = paginator.page(page) except PageNotAnInteger: paginated_data = paginator.page(1) except EmptyPage: paginated_data = paginator.page(paginator.num_pages) context['paginated_data'] = paginated_data if paginator.num_pages > 1: context['paginator'] = paginator return context