From c46a60ed8876c179b09ddd21db47606bdce0f505 Mon Sep 17 00:00:00 2001 From: Dirk Alders Date: Tue, 1 Sep 2020 12:37:25 +0200 Subject: [PATCH] Import and Export extended --- management/commands/_private.py | 5 +- management/commands/export_userdata.py | 70 +++++++++---- management/commands/import_userdata.py | 136 +++++++++++++++++++++++-- models.py | 17 ++++ 4 files changed, 199 insertions(+), 29 deletions(-) diff --git a/management/commands/_private.py b/management/commands/_private.py index b4119bf..a05ed05 100644 --- a/management/commands/_private.py +++ b/management/commands/_private.py @@ -1,4 +1,7 @@ -KEY_USERDATA_VERSION = 'version' KEY_USERDATA_FAVOURITE = 'favourite' KEY_USERDATA_TAGS = 'tag' +KEY_USER_PROFILE = 'userprofile' +KEY_THEME_BOTTOMBAR = 'bottombar' +KEY_THEME_SETTINGS = 'settings' KEY_USERDATA_UPLOAD = 'upload' +KEY_ACCESS_DATA = 'access_data' diff --git a/management/commands/export_userdata.py b/management/commands/export_userdata.py index c34d776..365cdcf 100644 --- a/management/commands/export_userdata.py +++ b/management/commands/export_userdata.py @@ -1,11 +1,17 @@ from django.contrib.auth.models import User from django.core.management.base import BaseCommand import json -from pygal.models import Tag +from themes.models import GetSettings +from themes.models import BottomBar +from users.models import UserProfile +from pygal.models import Item, Tag -from ._private import KEY_USERDATA_VERSION +from ._private import KEY_THEME_SETTINGS +from ._private import KEY_THEME_BOTTOMBAR +from ._private import KEY_USER_PROFILE from ._private import KEY_USERDATA_FAVOURITE from ._private import KEY_USERDATA_TAGS +from ._private import KEY_ACCESS_DATA class Command(BaseCommand): @@ -13,25 +19,55 @@ class Command(BaseCommand): def handle(self, *args, **options): data = {} - data[KEY_USERDATA_VERSION] = 1 + # + # Access + # + if KEY_ACCESS_DATA not in data: + data[KEY_ACCESS_DATA] = {} + # public_access + data[KEY_ACCESS_DATA][''] = [item.rel_path for item in Item.objects.filter(public_access=True)] + # user_access + for u in User.objects.all(): + data[KEY_ACCESS_DATA][u.username] = {} + data[KEY_ACCESS_DATA][u.username]['read_access'] = [item.rel_path for item in u.read_access.all()] + data[KEY_ACCESS_DATA][u.username]['modify_access'] = [item.rel_path for item in u.modify_access.all()] + # + # Favourites + # + if KEY_USERDATA_FAVOURITE not in data: + data[KEY_USERDATA_FAVOURITE] = {} for user in User.objects.all(): favourites = user.favourite_of.all() if len(favourites) > 0: - if KEY_USERDATA_FAVOURITE not in data: - data[KEY_USERDATA_FAVOURITE] = {} data[KEY_USERDATA_FAVOURITE][user.username] = [i.rel_path for i in favourites] + # + # Tags + # + if KEY_USERDATA_TAGS not in data: + data[KEY_USERDATA_TAGS] = {} for tag in Tag.objects.all(): - if KEY_USERDATA_TAGS not in data: - data[KEY_USERDATA_TAGS] = {} - if tag.item.rel_path not in data[KEY_USERDATA_TAGS]: - data[KEY_USERDATA_TAGS][tag.item.rel_path] = [] - tagdata = {} - tagdata['text'] = tag.text - if tag.has_valid_coordinates: - tagdata['topleft_x'] = tag.topleft_x - tagdata['topleft_y'] = tag.topleft_y - tagdata['bottomright_x'] = tag.bottomright_x - tagdata['bottomright_y'] = tag.bottomright_y - data[KEY_USERDATA_TAGS][tag.item.rel_path].append(tagdata) + tag_key = tag.export_key() + if tag_key not in data[KEY_USERDATA_TAGS]: + data[KEY_USERDATA_TAGS][tag_key] = [] + data[KEY_USERDATA_TAGS][tag.export_key()].append(tag.export_data()) + # + # Settings + # + s = GetSettings() + data[KEY_THEME_SETTINGS] = s.export_data() + # + # Bottombar + # + if KEY_THEME_BOTTOMBAR not in data: + data[KEY_THEME_BOTTOMBAR] = [] + for bb_entry in BottomBar.objects.all(): + data[KEY_THEME_BOTTOMBAR].append(bb_entry.export_data()) + # + # Userprofile + # + if KEY_USER_PROFILE not in data: + data[KEY_USER_PROFILE] = {} + for profile in UserProfile.objects.all(): + data[KEY_USER_PROFILE][profile.export_key()] = profile.export_data() self.stdout.write(json.dumps(data, indent=4, sort_keys=True)) diff --git a/management/commands/import_userdata.py b/management/commands/import_userdata.py index ed6b1f7..08d7a21 100644 --- a/management/commands/import_userdata.py +++ b/management/commands/import_userdata.py @@ -1,12 +1,17 @@ from django.contrib.auth.models import User from django.core.management.base import BaseCommand import json -from pygal.models import Item, Tag +from pygal.models import Item, Tag, TagExist +from themes.models import GetSettings, SettingExist, BottomBar, BottomBarExist import os -from ._private import KEY_USERDATA_VERSION from ._private import KEY_USERDATA_FAVOURITE from ._private import KEY_USERDATA_TAGS +from ._private import KEY_USER_PROFILE +from ._private import KEY_THEME_SETTINGS +from ._private import KEY_THEME_BOTTOMBAR +from users.models import UserProfile, UserprofilerExist +from pygal.management.commands._private import KEY_ACCESS_DATA class Command(BaseCommand): @@ -25,10 +30,6 @@ class Command(BaseCommand): try: with open(fn, 'r') as fh: data = json.load(fh) - try: - version = data.pop(KEY_USERDATA_VERSION) - except KeyError: - version = 1 except PermissionError: self.error_skipped_file(fn, 'file permission') except json.decoder.JSONDecodeError: @@ -42,8 +43,75 @@ class Command(BaseCommand): cnt_success = 0 cnt_already_exist = 0 cnt_user_missing = 0 + missing_users = [] cnt_item_missing = 0 - if section == KEY_USERDATA_FAVOURITE: + # + # Access + # + if section == KEY_ACCESS_DATA: + for username in data[section]: + if username == '': + # public_access + for rel_path in data[section][username]: + cnt_all_datasets += 1 + try: + item = Item.objects.get(rel_path=rel_path) + except User.DoesNotExist: + cnt_item_missing += 1 + else: + if item.public_access: + cnt_already_exist += 1 + else: + item.public_access = True + item.save() + cnt_success += 1 + else: + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + user = None + # read_access + for rel_path in data[section][username]['read_access']: + cnt_all_datasets += 1 + if user is None: + cnt_user_missing += 1 + if username not in missing_users: + missing_users.append(username) + else: + try: + item = Item.objects.get(rel_path=rel_path) + except User.DoesNotExist: + cnt_item_missing += 1 + else: + if user in item.read_access.all(): + cnt_already_exist += 1 + else: + item.read_access.add(user) + item.save() + cnt_success += 1 + # modify_access + for rel_path in data[section][username]['modify_access']: + cnt_all_datasets += 1 + if user is None: + cnt_user_missing += 1 + if username not in missing_users: + missing_users.append(username) + else: + try: + item = Item.objects.get(rel_path=rel_path) + except User.DoesNotExist: + cnt_item_missing += 1 + else: + if user in item.modify_access.all(): + cnt_already_exist += 1 + else: + item.modify_access.add(user) + item.save() + cnt_success += 1 + # + # Favourites + # + elif section == KEY_USERDATA_FAVOURITE: for username in data[section]: try: user = User.objects.get(username=username) @@ -53,6 +121,8 @@ class Command(BaseCommand): cnt_all_datasets += 1 if user is None: cnt_user_missing += 1 + if username not in missing_users: + missing_users.append(username) try: i = Item.objects.get(rel_path=rel_path) except Item.DoesNotExist: @@ -60,9 +130,12 @@ class Command(BaseCommand): else: if user in i.favourite_of.all(): cnt_already_exist += 1 - else: + elif user is not None: cnt_success += 1 i.favourite_of.add(user) + # + # Tags + # elif section == KEY_USERDATA_TAGS: for rel_path in data[section]: cnt_all_datasets += len(data[section][rel_path]) @@ -72,12 +145,53 @@ class Command(BaseCommand): cnt_item_missing += len(data[section][rel_path]) else: for tag_data in data[section][rel_path]: - if len(Tag.objects.filter(item=i, text=tag_data['text'])) > 0: + if TagExist(i, tag_data): cnt_already_exist += 1 else: tag_data['item'] = i Tag(**tag_data).save() cnt_success += 1 + # + # Settings + # + elif section == KEY_THEME_SETTINGS: + cnt_all_datasets = 1 + if SettingExist(data[section]): + cnt_already_exist += 1 + else: + s = GetSettings() + s.import_data(data[section]) + cnt_success += 1 + # + # Bottombar + # + elif section == KEY_THEME_BOTTOMBAR: + cnt_all_datasets = len(data[section]) + for bb_entry_import in data[section]: + if BottomBarExist(bb_entry_import): + cnt_already_exist += 1 + else: + bb_entry = BottomBar() + bb_entry.import_data(bb_entry_import) + cnt_success += 1 + # + # Userprofile + # + elif section == KEY_USER_PROFILE: + cnt_all_datasets = len(data[section]) + for username in data[section]: + if UserprofilerExist(username, data[section][username]): + cnt_already_exist += 1 + else: + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + cnt_user_missing += 1 + missing_users.append(username) + else: + profile = UserProfile(user=user) + profile.import_data(data[section][username]) + cnt_success += 1 else: self.stdout.write(self.style.ERROR(' Section unknown!')) # @@ -93,6 +207,6 @@ class Command(BaseCommand): self.stdout.write(style(' %5d %s(s) successfully added.' % (cnt_success, section))) self.stdout.write(style(' %5d %s(s) already set correctly.' % (cnt_already_exist, section))) if cnt_user_missing > 0: - self.stdout.write(self.style.ERROR(' %5d %s(s) not added, because the target user does not exist.' % (cnt_user_missing, section))) + self.stdout.write(self.style.ERROR(' %5d %s(s) not added, because the target user(s) %s do(es) not exist.' % (cnt_user_missing, section, repr(missing_users)))) if cnt_item_missing > 0: - self.stdout.write(self.style.ERROR(' %5d %s(s) not added, because the target item does not exist.' % (cnt_item_missing, section))) + self.stdout.write(self.style.ERROR(' %5d %s(s) not added, because the target item does not exist. Try python manage.py rebuild_cache to create items, if you import to a scratch database.' % (cnt_item_missing, section))) diff --git a/models.py b/models.py index 36dba60..9ff1387 100644 --- a/models.py +++ b/models.py @@ -447,6 +447,10 @@ class Item(models.Model): return 'Item: %s' % self.rel_path +def TagExist(item, data): + return len(Tag.objects.filter(item=item, text=data['text'])) > 0 + + class Tag(models.Model): item = models.ForeignKey(Item, on_delete=models.CASCADE) text = models.CharField(max_length=100) @@ -468,3 +472,16 @@ class Tag(models.Model): """the url to the Django admin interface for the model instance""" info = (self._meta.app_label, self._meta.model_name) return reverse('admin:%s_%s_change' % info, args=(self.pk,)) + + def export_key(self): + return self.item.rel_path + + def export_data(self): + rv = {} + rv['text'] = self.text + if self.has_valid_coordinates: + rv['topleft_x'] = self.topleft_x + rv['topleft_y'] = self.topleft_y + rv['bottomright_x'] = self.bottomright_x + rv['bottomright_y'] = self.bottomright_y + return rv