Как обрабатывать данные в Django (но это не зависит от Django!) - PullRequest
4 голосов
/ 31 марта 2012

У меня есть приложение Django, которое собирает информацию о композиторах (в музыкальном смысле) из различных источников - API, HTTP POSTs, соскребов и т. Д.

Как только эта информация агрегируется, она не очень высокаякачественный.Таким образом, у вас может быть «JS Bach» в одном месте, «JS Bach» в другом и другие ошибки.Это приводит к тому, что в моей таблице несколько строк, представляющих одного и того же человека.

Я хочу устранить эти дубликаты, сделав «JS Bach» канонической версией, и сделать так, чтобы, если мы когда-нибудь увидим «JS Bach»Мы знаем, чтобы исправить это.На самом деле вариаций достаточно много, но я рад, что процесс исправления является ручным с учетом человеческого фактора.

Поэтому мой вопрос в том, как лучше всего представить это в коде.?На данный момент моя модель:

class Composer(models.Model):
    name = models.CharField(max_length=100)

Должен ли я:

  • иметь новую модель ComposerCorrection, которая отображает composer_id на canonical_id?
  • Добавить опциональный canonical_id к модели Composer?
  • Что-то еще, что я не учел?

Стоит также упомянуть, что существуют другие отношения, которыезадействовать композитора, например Work, принадлежащего Composer.Когда произойдет исправление, эти идентификаторы также необходимо будет как-то перенаправить, но я думаю, что это не является основной проблемой.

Дайте мне знать, если вам нужна дополнительная информация!

Ответы [ 3 ]

2 голосов
/ 31 марта 2012

Добавление к ответа VascoP (я бы сделал это комментом, но в нем слишком много кода), вы можете сохранить его replace_dic в базе данных, чтобы вы могли добавлять исправления через например администратор Django, без необходимости изменения кода. Это может выглядеть так:

class ComposerCorrection(models.Model):
    wrong_name = models.CharField(max_length=100, unique=True)
    canonical_name = models.CharField(max_length=100)

def correct_name(name):
    try:
        return ComposerCorrection.objects.get(wrong_name=name).canonical_name
    except ComposerCorrection.DoesNotExist:
        return name

Затем вы можете поместить correct_name в метод save() Composer (или в качестве сигнала предварительного сохранения), а также добавить функцию VascoP correctComposer в качестве сигнала после сохранения для ComposerCorrection объектов, так что добавление нового исправит базу данных, не делая ничего другого.

1 голос
/ 31 марта 2012

Когда вы найдете неправильно названный Композитор, вы должны обновить эти отношения и удалить неправильно названный Composer:

def correctComposer(canonical_composer_name, wrong_composer_name):
  canonical_composer = Composer.objects.get(name__exact=canonical_composer_name)
  wrong_composer = Composer.objects.get(name__exact=wrong_composer_name)

  # repeat this for each relationship
  work = wrong_composer.work_set.all()
  for entry in work:
     entry.composer = canonical_composer

  correction.save()

  wrong_composer.delete()

РЕДАКТИРОВАТЬ: Это работает для ранее вставленных Композиторов.Для автокоррекции при вставке можно использовать другой метод, поскольку нам не нужно создавать новых композиторов, если уже есть канонический композитор, который ему подходит.

Для этого вы можете хранить словарь (который должен быть рядом с моделью для удобства чтения) и частые ошибки и функцию correcNames:

replace_dic = {
   'motzart' : 'Mozart',
   'j s bach' : 'J. S. Bach'
   }

def correctNames(name, dic):
   return dic.get(name.lower(), name)

Делая клавиши строчными, вы получаете регистр без учета регистразамена, которая является своего рода бонусом.

И тогда вы можете переопределить Composer метод сохранения следующим образом:

def save(self, *args, **kwargs):
   self.name = correctNames(self.name, replace_dic)
   super(Composer, self).save()
0 голосов
/ 31 марта 2012

Если Composer содержит только имя до завершения сбора данных, для простоты я могу предпочесть не нормализовать имя композитора в Composer, а сохранять его непосредственно в экземпляре Work. Так же, как

class Work(models.Model):
    composer_name = models.CharField(max_length=100)
    ...

И вручную выполнить фильтрацию по имени композитора и выполнить пакетное обновление в списке изменений администратора «Работа», с помощью фильтра и действия.

Затем можно создать экземпляры Composer и связать с ними экземпляр Work, или даже использовать имя_композитора в качестве первичного ключа Composer.

...