From 941f164c773d11ab4e704d434f32fb3aab608318 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 3 Mar 2017 16:28:22 +0100 Subject: [PATCH] import_site: add --clean, --if-empty and --overwrite options --- passerelle/apps/csvdatasource/models.py | 6 +++-- passerelle/base/management/commands/import_site.py | 21 ++++++++++++++++- passerelle/base/models.py | 27 ++++++++++++++-------- passerelle/utils/__init__.py | 6 ++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/passerelle/apps/csvdatasource/models.py b/passerelle/apps/csvdatasource/models.py index 7f7ca70..011e19f 100644 --- a/passerelle/apps/csvdatasource/models.py +++ b/passerelle/apps/csvdatasource/models.py @@ -383,10 +383,12 @@ class CsvDataSource(BaseResource): return d @classmethod - def import_json_real(cls, d, **kwargs): + def import_json_real(cls, overwrite, instance, d, **kwargs): queries = d.pop('queries', []) - instance = super(CsvDataSource, cls).import_json_real(d, **kwargs) + instance = super(CsvDataSource, cls).import_json_real(overwrite, instance, d, **kwargs) new = [] + if instance and overwrite: + Query.objects.filter(resource=instance).delete() for query in queries: q = Query.import_json(query) q.resource = instance diff --git a/passerelle/base/management/commands/import_site.py b/passerelle/base/management/commands/import_site.py index 612f5f0..cd2d13c 100644 --- a/passerelle/base/management/commands/import_site.py +++ b/passerelle/base/management/commands/import_site.py @@ -3,6 +3,7 @@ from optparse import make_option from django.core.management.base import BaseCommand +from passerelle.base.models import ApiUser, BaseResource from passerelle.utils import import_site @@ -12,7 +13,25 @@ class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--import-users', action='store_true', default=False, help='Import users and access rights'), + make_option('--if-empty', action='store_true', default=False, + help='Import only if passerelle is empty'), + make_option('--overwrite', action='store_true', default=False, + help='Overwirte existing resources'), ) + def is_empty(self, options): + if options['import_users']: + if ApiUser.objects.count(): + return False + + for subclass in BaseResource.__subclasses__(): + if subclass._meta.abstract: + continue + if subclass.objects.count(): + return False + return True + def handle(self, filename, **options): - import_site(json.load(open(filename)), import_users=options['import_users']) + if options['if_empty'] and not self.is_empty(): + return + import_site(json.load(open(filename)), overwrite=options['overwrite'], import_users=options['import_users']) diff --git a/passerelle/base/models.py b/passerelle/base/models.py index 29132f7..012b98c 100644 --- a/passerelle/base/models.py +++ b/passerelle/base/models.py @@ -62,13 +62,16 @@ class ApiUser(models.Model): } @classmethod - def import_json(self, d): + def import_json(self, d, overwrite=False): if d.get('@type') != 'passerelle-user': raise ValueError('not a passerelle user export') d = d.copy() d.pop('@type') - return self.objects.get_or_create(username=d['username'], - defaults=d) + api_user, created = self.objects.get_or_create(username=d['username'], defaults=d) + if overwrite and not created: + for key in d: + setattr(api_user, key, d[key]) + api_user.save() class TemplateVar(models.Model): @@ -219,7 +222,7 @@ class BaseResource(models.Model): return d @staticmethod - def import_json(d, import_users=False): + def import_json(d, import_users=False, overwrite=False): if d.get('@type') != 'passerelle-resource': raise ValueError('not a passerelle resource export') @@ -228,12 +231,14 @@ class BaseResource(models.Model): app_label, model_name = d['resource_type'].split('.') model = apps.get_model(app_label, model_name) try: - return model.objects.get(slug=d['slug']) + instance = model.objects.get(slug=d['slug']) + if not overwrite: + return except model.DoesNotExist: - pass + instance = None with transaction.atomic(): # prevent semi-creation of ressources - instance = model.import_json_real(d) + instance = model.import_json_real(overwrite, instance, d) resource_type = ContentType.objects.get_for_model(instance) # We can only connect AccessRight objects to the new Resource after its creation if import_users: @@ -247,7 +252,7 @@ class BaseResource(models.Model): return instance @classmethod - def import_json_real(cls, d, **kwargs): + def import_json_real(cls, overwrite, instance, d, **kwargs): init_kwargs = { 'title': d['title'], 'slug': d['slug'], @@ -255,7 +260,11 @@ class BaseResource(models.Model): 'log_level': d['log_level'], } init_kwargs.update(kwargs) - instance = cls(**init_kwargs) + if instance: + for key in init_kwargs: + setattr(instance, key, init_kwargs[key]) + else: + instance = cls(**init_kwargs) for field, model in cls._meta.get_concrete_fields_with_model(): if field.name == 'id': continue diff --git a/passerelle/utils/__init__.py b/passerelle/utils/__init__.py index aab32b6..f5bd24a 100644 --- a/passerelle/utils/__init__.py +++ b/passerelle/utils/__init__.py @@ -192,7 +192,7 @@ def export_site(): return d -def import_site(d, import_users=False): +def import_site(d, overwrite=False, import_users=False): '''Load passerelle configuration (users, resources and ACLs) from a dictionnary loaded from JSON ''' @@ -201,7 +201,7 @@ def import_site(d, import_users=False): with transaction.atomic(): if import_users: for apiuser in d['apiusers']: - ApiUser.import_json(apiuser) + ApiUser.import_json(apiuser, overwrite=overwrite) for resource in d['resources']: - BaseResource.import_json(resource, import_users=import_users) + BaseResource.import_json(resource, overwrite=overwrite, import_users=import_users) -- 2.1.4