Как хранить несколько копий одного и того же поля в Django? - PullRequest
1 голос
/ 02 февраля 2011

Я храню метаданные OLAC , которые описывают лингвистические ресурсы. Многие из элементов метаданных являются повторяемыми - например, ресурс может иметь два языка, три автора и четыре даты, связанные с ним.

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

Ответы [ 2 ]

4 голосов
/ 02 февраля 2011

Похоже, что наилучшим способом было бы через множество отношений, например:

class author(models.Model):
    # fields?

class language(models.Model):
    iso_lang_code = models.CharField() # probably need some constraints here

class resource(models.Model):
    name = models.CharField()
    authors = models.ManyToManyField(Author)
    languages = models.ManyToManyField(Language)

Затем, когда дело доходит до создания ресурса, вы просто делаете:

r = resource(name="")
a1 = author(name="ninefingers")
a2 = author(name="jon skeet", type="god")
r.authors.add(a1)
r.authors.add(a2)
english = languages.objects.get(iso_lang_code="en-GB")
r.add(english)
r.save()

И вы также можете сделать некоторые действительно причудливые вещи, такие как:

english = languages.objects.get(iso_lang_code="en-GB")
resourcesinenglish = english.resource_set.all()

for r in resourcesinenglish:
    # do something on r.

Так что использование ORM таким способом действительно мощно. Да, вы в основном получаете список языков ISO в таблице SQL, но это проблема? Если это так, вы всегда можете заменить его на строка и использовать objects.filter(language='en-GB'), что (примерно) переводит в sql из WHERE language='en-GB'. Конечно, вы ограничены только одним языком.

Другим подходом может быть написание всех языков в виде кодов ISO, модифицированных разделителем, скажем ; затем выполните

r = resource.objects.get(id=701)
langs = r.languages.split(';')
for l in language:
    print l

Конечно, поддерживать этот список становится все труднее. Я думаю, что ORM намного проще.

Что касается более сложных типов, таких как Authors, то ORM - самый простой способ.

Обратите внимание, что если вас беспокоит количество запросов к базе данных, которые он создает, вы всегда можете использовать select_near. Это именно так, как звучит - следует всем внешним ключам, поэтому ваша база данных получает один массивный удар, а затем остается один, поскольку объекты находятся в памяти (кэшируются).

0 голосов
/ 02 февраля 2011

Вы также можете выбрать элемент tag.Это может иметь два поля, тип и значение.Примерно так:

class TagType(models.Model):
    name = models.CharField(max_length=50)

class Tag(models.Model):
    type = models.ManyToManyField(TagType)
    value = models.CharField(max_length=200)

class Resource(models.Model):
    name = models.CharField(max_length=50)
    tag = models.ManyToManyField(Tag)

Вы можете выбрать тип тега как поле char, но я предпочитаю, чтобы это была отдельная модель, потому что вы можете использовать интерфейс администратора для ввода серии типов, а затемвыберите их из выпадающего списка, если вы хотите добавить новый тег.

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

...