Skip to content
This repository was archived by the owner on Oct 15, 2020. It is now read-only.

Commit a523376

Browse files
committed
Allow to control version fields
1 parent 21593cc commit a523376

8 files changed

+260
-225
lines changed

ban/core/models.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class BaseModel(BaseResource, BaseVersioned):
2323
class Model(ResourceModel, Versioned, metaclass=BaseModel):
2424
resource_fields = ['version', 'created_at', 'created_by', 'modified_at',
2525
'modified_by', 'attributes']
26-
exclude_for_compact = ['version', 'created_at', 'created_by',
27-
'modified_at', 'modified_by']
26+
exclude_for_collection = ['version', 'created_at', 'created_by',
27+
'modified_at', 'modified_by']
2828
# 'version' is validated by us.
2929
resource_schema = {'version': {'required': False},
3030
'created_at': {'readonly': True},
@@ -58,6 +58,7 @@ def __str__(self):
5858
class Municipality(NamedModel):
5959
identifiers = ['siren', 'insee']
6060
resource_fields = ['name', 'alias', 'insee', 'siren', 'postcodes']
61+
exclude_for_version = ['postcodes']
6162

6263
insee = db.CharField(max_length=5, unique=True)
6364
siren = db.CharField(max_length=9, unique=True, null=True)

ban/core/resource.py

+24-16
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def as_resource_list(self):
3434

3535
class BaseResource(peewee.BaseModel):
3636

37-
def include_field_for_compact(cls, name):
38-
if name in cls.exclude_for_compact:
37+
def include_field_for_collection(cls, name):
38+
if name in cls.exclude_for_collection:
3939
return False
4040
attr = getattr(cls, name, None)
4141
exclude = (db.ManyToManyField, peewee.ReverseRelationDescriptor,
@@ -48,7 +48,8 @@ def __new__(mcs, name, bases, attrs, **kwargs):
4848
# Inherit and extend instead of replacing.
4949
resource_fields = attrs.pop('resource_fields', None)
5050
resource_schema = attrs.pop('resource_schema', None)
51-
exclude_for_compact = attrs.pop('exclude_for_compact', None)
51+
exclude_for_collection = attrs.pop('exclude_for_collection', None)
52+
exclude_for_version = attrs.pop('exclude_for_version', None)
5253
cls = super().__new__(mcs, name, bases, attrs, **kwargs)
5354
if resource_fields is not None:
5455
inherited = getattr(cls, 'resource_fields', {})
@@ -58,14 +59,20 @@ def __new__(mcs, name, bases, attrs, **kwargs):
5859
inherited = getattr(cls, 'resource_schema', {})
5960
resource_schema.update(inherited)
6061
cls.resource_schema = resource_schema
61-
if exclude_for_compact is not None:
62-
inherited = getattr(cls, 'exclude_for_compact', [])
63-
exclude_for_compact.extend(inherited)
64-
cls.exclude_for_compact = exclude_for_compact
65-
cls.extended_fields = cls.resource_fields
66-
cls.compact_fields = [
67-
n for n in cls.extended_fields
68-
if mcs.include_field_for_compact(cls, n)] + ['resource']
62+
if exclude_for_collection is not None:
63+
inherited = getattr(cls, 'exclude_for_collection', [])
64+
exclude_for_collection.extend(inherited)
65+
cls.exclude_for_collection = exclude_for_collection
66+
if exclude_for_version is not None:
67+
inherited = getattr(cls, 'exclude_for_version', [])
68+
exclude_for_version.extend(inherited)
69+
cls.exclude_for_version = exclude_for_version
70+
cls.collection_fields = [
71+
n for n in cls.resource_fields
72+
if mcs.include_field_for_collection(cls, n)] + ['resource']
73+
cls.versioned_fields = [
74+
n for n in cls.resource_fields
75+
if n not in cls.exclude_for_version]
6976
cls.build_resource_schema()
7077
return cls
7178

@@ -74,7 +81,8 @@ class ResourceModel(db.Model, metaclass=BaseResource):
7481
resource_fields = ['id']
7582
identifiers = []
7683
resource_schema = {'id': {'readonly': True}}
77-
exclude_for_compact = []
84+
exclude_for_collection = []
85+
exclude_for_version = []
7886

7987
id = db.CharField(max_length=50, unique=True, null=False)
8088

@@ -96,7 +104,7 @@ def build_resource_schema(cls):
96104
"""Map Peewee models to Cerberus validation schema."""
97105
schema = dict(cls.resource_schema)
98106
for name, field in cls._meta.fields.items():
99-
if name not in cls.extended_fields:
107+
if name not in cls.resource_fields:
100108
continue
101109
if field.primary_key:
102110
continue
@@ -138,17 +146,17 @@ def resource(self):
138146
@property
139147
def as_resource(self):
140148
"""Resource plus relations."""
141-
return {f: self.extended_field(f) for f in self.extended_fields}
149+
return {f: self.extended_field(f) for f in self.resource_fields}
142150

143151
@property
144152
def as_relation(self):
145153
"""Resources plus relation references without metadata."""
146-
return {f: self.compact_field(f) for f in self.compact_fields}
154+
return {f: self.compact_field(f) for f in self.collection_fields}
147155

148156
@property
149157
def as_version(self):
150158
"""Resources plus relations references and metadata."""
151-
return {f: self.compact_field(f) for f in self.extended_fields}
159+
return {f: self.compact_field(f) for f in self.versioned_fields}
152160

153161
def extended_field(self, name):
154162
value = getattr(self, '{}_extended'.format(name), getattr(self, name))

ban/tests/test_diff.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from .factories import MunicipalityFactory
2+
3+
4+
def test_only_changed_columns_should_be_in_diff():
5+
municipality = MunicipalityFactory(name='Moret-sur-Loing', insee='77316',
6+
siren='987654321')
7+
municipality.name = 'Orvanne'
8+
municipality.siren = '123456789'
9+
# "Changed" with same value.
10+
municipality.insee = '77316'
11+
municipality.increment_version()
12+
municipality.save()
13+
diff = municipality.versions[1].diff
14+
assert len(diff.diff) == 2 # name, siren
15+
assert diff.diff['name']['old'] == 'Moret-sur-Loing'
16+
assert diff.diff['name']['new'] == 'Orvanne'
17+
assert diff.diff['siren']['old'] == '987654321'
18+
assert diff.diff['siren']['new'] == '123456789'
19+
municipality.insee = '77319'
20+
municipality.increment_version()
21+
municipality.save()
22+
diff = municipality.versions[2].diff
23+
assert len(diff.diff) == 1 # insee
24+
assert diff.diff['insee']['old'] == '77316'
25+
assert diff.diff['insee']['new'] == '77319'
26+
27+
28+
def test_adding_value_to_arrayfield_column():
29+
municipality = MunicipalityFactory(name='Moret-sur-Loing')
30+
municipality.alias = ['Orvanne']
31+
municipality.increment_version()
32+
municipality.save()
33+
diff = municipality.versions[1].diff
34+
assert len(diff.diff) == 1 # name, siren
35+
assert diff.diff['alias']['old'] is None
36+
assert diff.diff['alias']['new'] == ['Orvanne']

ban/tests/test_managers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from ban.core import models
22

3-
from .factories import MunicipalityFactory, GroupFactory
3+
from .factories import GroupFactory, MunicipalityFactory
44

55

66
def test_municipality_as_resource():

0 commit comments

Comments
 (0)