Projet

Général

Profil

0001-general-add-basic-export-import-of-named-assets-2493.patch

Frédéric Péters, 18 juillet 2018 10:33

Télécharger (5,57 ko)

Voir les différences:

Subject: [PATCH] general: add basic export/import of named assets (#24933)

 combo/apps/assets/models.py | 34 ++++++++++++++++++++++++++++++++++
 combo/data/utils.py         |  8 +++++++-
 tests/test_import_export.py | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 1 deletion(-)
combo/apps/assets/models.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import json
18

  
19
from django.core import serializers
17 20
from django.db import models
18 21

  
22
class AssetManager(models.Manager):
23
    def get_by_natural_key(self, key):
24
        return self.get(key=key)
25

  
26

  
19 27
class Asset(models.Model):
28
    objects = AssetManager()
29

  
20 30
    key = models.CharField(max_length=128, unique=True)
21 31
    asset = models.FileField(upload_to='assets')
32

  
33
    @classmethod
34
    def export_all_for_json(cls):
35
        return [x.get_as_serialized_object() for x in Asset.objects.all()]
36

  
37
    def get_as_serialized_object(self):
38
        serialized_asset = json.loads(serializers.serialize('json', [self],
39
            use_natural_foreign_keys=True, use_natural_primary_keys=True))[0]
40
        del serialized_asset['model']
41
        del serialized_asset['pk']
42
        return serialized_asset
43

  
44
    @classmethod
45
    def load_serialized_objects(cls, json_site):
46
        for json_asset in json_site:
47
            cls.load_serialized_object(json_asset)
48

  
49
    @classmethod
50
    def load_serialized_object(cls, json_asset):
51
        json_asset['model'] = 'assets.asset'
52
        asset, created = Asset.objects.get_or_create(key=json_asset['fields']['key'])
53
        json_asset['pk'] = asset.id
54
        asset = [x for x in serializers.deserialize('json', json.dumps([json_asset]))][0]
55
        asset.save()
combo/data/utils.py
18 18
from django.db import transaction
19 19
from django.utils.translation import ugettext_lazy as _
20 20

  
21
from combo.apps.assets.models import Asset
21 22
from combo.apps.maps.models import MapLayer
22 23
from .models import Page
23 24

  
......
33 34
def export_site():
34 35
    '''Dump site objects to JSON-dumpable dictionnary'''
35 36
    return {'pages': Page.export_all_for_json(),
36
            'map-layers': MapLayer.export_all_for_json()}
37
            'map-layers': MapLayer.export_all_for_json(),
38
            'assets': Asset.export_all_for_json(),}
37 39

  
38 40

  
39 41
def import_site(data, if_empty=False, clean=False):
......
61 63

  
62 64
    if clean:
63 65
        MapLayer.objects.all().delete()
66
        Asset.objects.all().delete()
64 67
        Page.objects.all().delete()
65 68

  
66 69
    with transaction.atomic():
67 70
        MapLayer.load_serialized_objects(data.get('map-layers') or [])
68 71

  
72
    with transaction.atomic():
73
        Asset.load_serialized_objects(data.get('assets') or [])
74

  
69 75
    with transaction.atomic():
70 76
        Page.load_serialized_pages(data.get('pages') or [])
tests/test_import_export.py
8 8

  
9 9
import pytest
10 10
from django.contrib.auth.models import Group
11
from django.core.files import File
11 12
from django.core.management import call_command
12 13

  
14
from combo.apps.assets.models import Asset
13 15
from combo.apps.maps.models import MapLayer, Map
14 16
from combo.data.models import Page, TextCell
15 17
from combo.data.utils import export_site, import_site, MissingGroups
......
33 35
    MapLayer(label='Foo', slug='foo', geojson_url='http://example.net/foo/').save()
34 36
    MapLayer(label='Bar', slug='bar', geojson_url='http://example.net/bar/').save()
35 37

  
38
@pytest.fixture
39
def some_assets():
40
    Asset(key='banner', asset=File(StringIO('test'), 'test.png')).save()
41
    Asset(key='favicon', asset=File(StringIO('test2'), 'test2.png')).save()
42

  
36 43
def get_output_of_command(command, *args, **kwargs):
37 44
    old_stdout = sys.stdout
38 45
    output = sys.stdout = StringIO()
......
162 169

  
163 170
    cell = TextCell.objects.get(order=0)
164 171
    assert [x.name for x in cell.groups.all()] == ['A Group']
172

  
173
def test_import_export_assets(app, some_assets):
174
    output = get_output_of_command('export_site')
175
    assert len(json.loads(output)['assets']) == 2
176
    import_site(data={}, clean=True)
177
    assert Asset.objects.all().count() == 0
178
    empty_output = get_output_of_command('export_site')
179
    assert len(json.loads(empty_output)['assets']) == 0
180

  
181
    Asset(key='footer', asset=File(StringIO('test3'), 'test3.png')).save()
182
    old_stdin = sys.stdin
183
    sys.stdin = StringIO(json.dumps({}))
184
    assert Asset.objects.count() == 1
185
    try:
186
        call_command('import_site', '-', clean=True)
187
    finally:
188
        sys.stdin = old_stdin
189
    assert Asset.objects.count() == 0
190

  
191
    with tempfile.NamedTemporaryFile() as f:
192
        f.write(output)
193
        f.flush()
194
        call_command('import_site', f.name)
195

  
196
    assert Asset.objects.count() == 2
197

  
198
    import_site(data={}, if_empty=True)
199
    assert Asset.objects.count() == 2
165
-