X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/c4309c888873728d417c2964c40cb9d03a89d441..180cb43d814a4abe2811f29630ffffaaf9cfa9b7:/src/catalogue/wikidata.py diff --git a/src/catalogue/wikidata.py b/src/catalogue/wikidata.py index 3ec843a7..e5aecafe 100644 --- a/src/catalogue/wikidata.py +++ b/src/catalogue/wikidata.py @@ -7,11 +7,11 @@ from django.db import models from django.db.models.signals import m2m_changed from django.utils.html import format_html from django.utils.translation import gettext_lazy as _ -from django.dispatch import receiver from wikidata.client import Client from wikidata.datavalue import DatavalueError from modeltranslation.translator import translator from modeltranslation.settings import AVAILABLE_LANGUAGES +from .wikimedia import Downloadable class WikidataModel(models.Model): @@ -23,33 +23,57 @@ class WikidataModel(models.Model): class Meta: abstract = True - - def wikidata_populate_field(self, client, entity, attname, wd, save, lang): - model_field = self._meta.get_field(attname) - if isinstance(model_field, models.ManyToManyField): - if getattr(self, attname).all().exists(): - return - else: - if getattr(self, attname): - return + def get_wikidata_property(self, client, entity, wd, lang): wdvalue = None - if wd == "description": + + if callable(wd): + return wd( + lambda next_arg: + self.get_wikidata_property( + client, entity, next_arg, lang + ) + ) + elif wd == "description": wdvalue = entity.description.get(lang, str(entity.description)) elif wd == "label": wdvalue = entity.label.get(lang, str(entity.label)) - else: + elif wd[0] == 'P': try: # TODO: lang? wdvalue = entity.get(client.get(wd)) except DatavalueError: pass + else: + try: + # wiki links identified as 'plwiki' etc. + wdvalue = entity.attributes['sitelinks'][wd]['url'] + except KeyError: + pass + return wdvalue + + + def wikidata_populate_field(self, client, entity, attname, wd, save, lang, force=False): + if not force: + model_field = self._meta.get_field(attname) + if isinstance(model_field, models.ManyToManyField): + if getattr(self, attname).all().exists(): + return + else: + if getattr(self, attname): + return + + wdvalue = self.get_wikidata_property(client, entity, wd, lang) + self.set_field_from_wikidata(attname, wdvalue, save=save) - def wikidata_populate(self, save=True): + def wikidata_populate(self, save=True, force=False): Wikidata = type(self).Wikidata client = Client() + client.opener.addheaders = [( + 'User-Agent', 'Wolne Lektury Redakcja / Python-wikidata' + )] # Probably should getlist entity = client.get(self.wikidata) for attname in dir(Wikidata): @@ -57,10 +81,10 @@ class WikidataModel(models.Model): continue wd = getattr(Wikidata, attname) - self.wikidata_populate_attribute(client, entity, attname, wd, save=save) + self.wikidata_populate_attribute(client, entity, attname, wd, save=save, force=force) if hasattr(Wikidata, '_supplement'): for attname, wd in Wikidata._supplement(self): - self.wikidata_populate_attribute(client, entity, attname, wd, save=save) + self.wikidata_populate_attribute(client, entity, attname, wd, save=save, force=force) def wikidata_fields_for_attribute(self, attname): field = getattr(type(self), attname) @@ -78,9 +102,9 @@ class WikidataModel(models.Model): yield attname, settings.LANGUAGE_CODE - def wikidata_populate_attribute(self, client, entity, attname, wd, save): + def wikidata_populate_attribute(self, client, entity, attname, wd, save, force=False): for fieldname, lang in self.wikidata_fields_for_attribute(attname): - self.wikidata_populate_field(client, entity, fieldname, wd, save, lang) + self.wikidata_populate_field(client, entity, fieldname, wd, save, lang, force=force) def save(self, **kwargs): am_new = self.pk is None @@ -97,6 +121,7 @@ class WikidataModel(models.Model): return # Find out what this model field is model_field = self._meta.get_field(attname) + skip_set = False if isinstance(model_field, models.ForeignKey): rel_model = model_field.related_model if issubclass(rel_model, WikidataModel): @@ -126,9 +151,27 @@ class WikidataModel(models.Model): if isinstance(wdvalue, date): if isinstance(model_field, models.IntegerField): wdvalue = wdvalue.year - elif not isinstance(wdvalue, str): + + # If downloadable (and not save)? + elif isinstance(wdvalue, Downloadable): + if save: + wdvalue.apply_to_field(self, attname) + skip_set = True + + elif hasattr(wdvalue, 'label'): wdvalue = wdvalue.label.get(language, str(wdvalue.label)) - setattr(self, attname, wdvalue) + + if not skip_set: + try: + wdvalue = model_field.to_python(wdvalue) + except: + pass + else: + if isinstance(wdvalue, str): + max_length = getattr(model_field, 'max_length', None) + if max_length: + wdvalue = wdvalue[:max_length] + setattr(self, attname, wdvalue) def wikidata_link(self): if self.wikidata: