如何在Django中存储同一字段的多个副本?

时间:2011-02-01 22:54:22

标签: python django django-models

我正在存储描述语言资源的OLAC metadata。元数据的许多元素都是可重复的 - 例如,资源可以有两种语言,三种作者和四种与之相关的日期。

有没有办法将其存储在一个模型中?为每个可重复的元数据元素定义模型似乎有些过分 - 特别是因为模型只有一个字段:它的值。

2 个答案:

答案 0 :(得分:4)

听起来最好的方式是通过多对多的关系,比如:

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这种方式非常强大。是的,你基本上最终得到了SQL表中的ISO语言列表,但这是一个问题吗?如果是这样,你总是可以用一个替换它 字符串并使用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。这听起来完全是听起来像 - 跟随所有外键,所以你的数据库被大量击中然后被单独留下,因为对象然后在内存中(缓存)。

答案 1 :(得分:0)

您也可以选择执行'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)

您可以选择让标签类型为charfield,但我更喜欢将其作为单独的模型,因为您可以使用管理界面输入一系列类型,然后在您希望的时候从下拉列表中选择它们添加新标签。

编辑:我应该注意上面的解决方案更好,因为它可以让以后更容易处理数据。如果您要做的不仅仅是输入此信息,我建议您定义完整的模型。