-
Notifications
You must be signed in to change notification settings - Fork 28
/
base.py
142 lines (113 loc) · 4.42 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from __future__ import unicode_literals
import re
import uuid
from django.db import models
from django.contrib.postgres.fields import ArrayField, JSONField
from django.core.validators import RegexValidator
from ... import common
class OCDIDField(models.CharField):
def __init__(self, *args, **kwargs):
self.ocd_type = kwargs.pop("ocd_type")
if self.ocd_type != "jurisdiction":
kwargs["default"] = lambda: "ocd-{}/{}".format(self.ocd_type, uuid.uuid4())
# len('ocd-') + len(ocd_type) + len('/') + len(uuid)
# = 4 + len(ocd_type) + 1 + 36
# = len(ocd_type) + 41
kwargs["max_length"] = 41 + len(self.ocd_type)
regex = (
"^ocd-" + self.ocd_type + "/[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$"
)
else:
kwargs["max_length"] = 300
regex = common.JURISDICTION_ID_REGEX
kwargs["primary_key"] = True
# get pattern property if it exists, otherwise just return the object (hopefully a string)
msg = "ID must match " + getattr(regex, "pattern", regex)
kwargs["validators"] = [RegexValidator(regex=regex, message=msg, flags=re.U)]
super(OCDIDField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(OCDIDField, self).deconstruct()
if self.ocd_type != "jurisdiction":
kwargs.pop("default")
kwargs.pop("max_length")
kwargs.pop("primary_key")
kwargs["ocd_type"] = self.ocd_type
return (name, path, args, kwargs)
class OCDBase(models.Model):
""" common base fields across all top-level models """
created_at = models.DateTimeField(
auto_now_add=True, help_text="The date and time of creation."
)
updated_at = models.DateTimeField(
auto_now=True, help_text="The date and time of the last update."
)
extras = JSONField(
default=dict,
blank=True,
help_text="A key-value store for storing arbitrary information not covered elsewhere.",
)
locked_fields = ArrayField(base_field=models.TextField(), blank=True, default=list)
class Meta:
abstract = True
class RelatedBase(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Meta:
abstract = True
class LinkBase(RelatedBase):
note = models.CharField(
max_length=300,
blank=True,
help_text="A short, optional note related to an object.",
)
url = models.URLField(
max_length=2000, help_text="A hyperlink related to an object."
)
class Meta:
abstract = True
def __str__(self):
return self.url
class MimetypeLinkBase(RelatedBase):
media_type = models.CharField(max_length=100)
url = models.URLField(max_length=2000)
text = models.TextField(default="", blank=True)
class Meta:
abstract = True
class IdentifierBase(RelatedBase):
identifier = models.CharField(
max_length=300,
help_text="A unique identifier developed by an upstream or third party source.",
)
scheme = models.CharField(
max_length=300, help_text="The name of the service that created the identifier."
)
class Meta:
abstract = True
def __str__(self):
return self.identifier
class RelatedEntityBase(RelatedBase):
name = models.CharField(max_length=2000)
entity_type = models.CharField(max_length=20, blank=True)
# optionally tied to an organization or person if it was linkable
# for these two on_delete is SET_NULL so that deletion of a linked entity doesn't
# delete this object- it should instead just become unresolved (NULL)
organization = models.ForeignKey(
"core.Organization", null=True, on_delete=models.SET_NULL
)
person = models.ForeignKey("core.Person", null=True, on_delete=models.SET_NULL)
@property
def entity_name(self):
if self.entity_type == "organization" and self.organization_id:
return self.organization.name
elif self.entity_type == "person" and self.person_id:
return self.person.name
else:
return self.name
@property
def entity_id(self):
if self.entity_type == "organization":
return self.organization_id
if self.entity_type == "person":
return self.person_id
return None
class Meta:
abstract = True