X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/0251adf97488c11e936a714976261febfb8c5268..9b533fdbfd08bd764744ae3a0d4717c87b61cf18:/src/catalogue/wikidata.py diff --git a/src/catalogue/wikidata.py b/src/catalogue/wikidata.py index b5f3e94f..731e55f2 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,31 +23,52 @@ 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() # Probably should getlist @@ -57,26 +78,30 @@ 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) if type(self) in translator._registry: - opts = translator.get_options_for_model(type(self)) - if attname in opts.fields: - tfields = opts.fields[attname] - for tf in tfields: - yield tf.name, tf.language - return + try: + opts = translator.get_options_for_model(type(self)) + except: + pass + else: + if attname in opts.fields: + tfields = opts.fields[attname] + for tf in tfields: + yield tf.name, tf.language + return 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 @@ -93,6 +118,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): @@ -122,9 +148,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: