我正在存储描述语言资源的OLAC metadata。元数据的许多元素都是可重复的 - 例如,资源可以有两种语言,三种作者和四种与之相关的日期。
有没有办法将其存储在一个模型中?为每个可重复的元数据元素定义模型似乎有些过分 - 特别是因为模型只有一个字段:它的值。
答案 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,但我更喜欢将其作为单独的模型,因为您可以使用管理界面输入一系列类型,然后在您希望的时候从下拉列表中选择它们添加新标签。
编辑:我应该注意上面的解决方案更好,因为它可以让以后更容易处理数据。如果您要做的不仅仅是输入此信息,我建议您定义完整的模型。