Added DCMeta - EAV based application to represent document meta-data. Started to...
[redakcja.git] / apps / dcmeta / models.py
1 from django.db import models
2 import eav.models
3 import pdb
4
5 # Some monkey patches to EAV:
6
7 # Allow dots & stuff
8 eav.models.slugify = lambda x: x
9
10 # Allow more characters 
11 eav.models.BaseSchema._meta.get_field_by_name("name")[0].max_length = 200
12
13 from django.contrib.auth.models import User
14 from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
15 from django.contrib.contenttypes.models import ContentType
16
17 from lxml import etree
18 from dcmeta.utils import RDFNS, common_prefixes, NamespaceDescriptor
19 import logging
20
21 logger = logging.getLogger("django.dcmeta")
22
23 class Description(eav.models.BaseEntity):
24     """Collection of meta-data that can be assigned to an entity."""
25     object_id = models.PositiveIntegerField(blank=True, null=True)
26     content_type = models.ForeignKey(ContentType, blank=True, null=True)
27
28     about = GenericForeignKey()
29     about_uri = models.TextField()
30
31     attrs = GenericRelation('Attr', object_id_field="entity_id", content_type_field="entity_type")
32
33     # shortcuts to EAV attributes
34     dublincore = NamespaceDescriptor('http://purl.org/dc/elements/1.1/')
35     marcrel = NamespaceDescriptor('http://www.loc.gov/loc.terms/relators/')
36
37     @classmethod
38     def get_schemata_for_model(self):
39         return Schema.objects.all()
40
41     @classmethod
42     def import_rdf(cls, text):
43         doc = etree.fromstring(text)
44         xml_desc = doc.xpath('/rdf:RDF/rdf:Description', namespaces={"rdf": RDFNS.uri})
45
46         if not xml_desc:
47             raise ValueError("Invalid document structure.")
48
49         xml_desc = xml_desc[0]
50
51         desc = Description.objects.create(about_uri=xml_desc.get(RDFNS("about")))
52
53         for xml_property in xml_desc.iterchildren():
54             property, _created = Schema.objects.get_or_create(
55                                 name=xml_property.tag, datatype=Schema.TYPE_TEXT)
56             property.save_attr(desc, xml_property.text)
57
58         desc = Description.objects.get(pk=desc.pk)
59         return desc
60
61     def __getitem__(self, key):
62         if not isinstance(key, tuple):
63             raise ValueError
64         ns, attr = key
65
66         if ns in common_prefixes: # URI given, value stored as prefix
67             ns = common_prefixes[ns]
68
69         return getattr(self, "{%s}%s" % (ns, attr))
70
71     def __setitem__(self, key, value):
72         return setattr(self, "dc_" + key, value)
73
74 class Schema(eav.models.BaseSchema):
75     pass
76
77 class Choice(eav.models.BaseChoice):
78     """
79         For properties with multiply values.
80     """
81     schema = models.ForeignKey(Schema, related_name='choices')
82
83 class Attr(eav.models.BaseAttribute):
84     schema = models.ForeignKey(Schema, related_name='attrs')
85     choice = models.ForeignKey(Choice, blank=True, null=True)