Skip to content

Commit

Permalink
feat: implement dumpdata view
Browse files Browse the repository at this point in the history
This view provides a way to serialize the whole database using json -
getting a fixture with natural foreign keys. This fixture lets us
reimport the database in a new installation.

Closes: #273
  • Loading branch information
b1rger committed Nov 20, 2023
1 parent d560fe8 commit 4a9cd11
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
73 changes: 73 additions & 0 deletions apis_core/core/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from django.http import HttpResponse
from django.views import View
from django.contrib.auth.mixins import UserPassesTestMixin

from django.apps import apps
from django.core import serializers
from django.db import DEFAULT_DB_ALIAS, router

from apis_core.apis_entities.models import AbstractEntity


class Dumpdata(UserPassesTestMixin, View):
"""
This view is loosely based on the `dumpdata` admin command.
It iterates throug the relevant app models and exports them using
the json serializer and natural foreign keys.
This way we can reimport this into a newly created Django APIS app
"""

def test_func(self):
return self.request.user.is_staff

def get_objects(self, models, *args, **kwargs):
for model in models:
if not model._meta.proxy and router.allow_migrate_model(
DEFAULT_DB_ALIAS, model
):
objects = model._default_manager
queryset = objects.using(DEFAULT_DB_ALIAS).order_by(model._meta.pk.name)
yield from queryset.iterator()

def get(self, request, *args, **kwargs):
# get all APIS apps and all APIS models
apis_app_labels = ["apis_relations", "apis_metainfo"]
apis_app_models = [
model
for model in apps.get_models()
if model._meta.app_label in apis_app_labels
]

# create a list of app labels we want to iterate
# this allows to extend the apps via the ?app_labels= parameter
app_labels = set(apis_app_labels)
app_labels |= set(request.GET.get("app_labels", []))

# look for models that inherit from APIS models and add their
# app label to app_labels
for model in apps.get_models():
if any(map(lambda x: issubclass(model, x), apis_app_models)):
app_labels.add(model._meta.app_label)

# now go through all app labels
app_list = {}
for app_label in app_labels:
app_config = apps.get_app_config(app_label)
app_list[app_config] = None

models = serializers.sort_dependencies(app_list.items(), allow_cycles=True)

headers = {
"Content-Type": "application/json",
}
hr = HttpResponse(headers=headers)

serializers.serialize(
"json",
self.get_objects(models),
indent=2,
use_natural_foreign_keys=True,
stream=hr,
)

return hr
3 changes: 3 additions & 0 deletions apis_core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ def build_apis_mock_request(method, path, view, original_request, **kwargs):
return request


from apis_core.core.views import Dumpdata

urlpatterns = [
path("", TemplateView.as_view(template_name="base.html"), name="apis_index"),
path("admin/", admin.site.urls),
Expand Down Expand Up @@ -160,6 +162,7 @@ def build_apis_mock_request(method, path, view, original_request, **kwargs):
),
# url(r'^docs/', include('sphinxdoc.urls')),
# url(r'^accounts/', include('registration.backends.simple.urls')),
path("dumpdata.json", Dumpdata.as_view()),
]

if "apis_fulltext_download" in settings.INSTALLED_APPS:
Expand Down

0 comments on commit 4a9cd11

Please sign in to comment.