Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: workaround for content types, but not so much for auth #2

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions django_migration_fixture/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import os

from django.core import serializers
from django.core.management.color import no_style
from django.db import connection
from django.db.models import signals


class FixtureObjectDoesNotExist(Exception):
"""Raised when attempting to roll back a fixture and the instance can't be found"""
pass


def reset_db_sequences(models):
if not models:
return
with connection.cursor() as cursor:
for sql in connection.ops.sequence_reset_sql(no_style(), models):
cursor.execute(sql)


def fixture(app, fixtures, fixtures_dir='fixtures', raise_does_not_exist=False):
"""
Load fixtures using a data migration.
Expand Down Expand Up @@ -35,9 +47,32 @@ def get_objects():
for obj in objects:
yield obj

def load_fixture(apps, schema_editor):
for obj in get_objects():
obj.save()
def load_fixture(app_config, schema_editor):
"""Entrypoint for RunPython to load the fixture.

This delays the actual loading until this app itself is being called
through the post_migrate signal hook. This is necessary for
the contenttypes and auth data to be available.

After the fixture has been loaded the database sequences for affected
models are being 'reset' (using `coalesce` with PostgreSQL)."""

def signal_handler(app_config, sender, **kwargs):
if sender.label == "django_migration_fixture":
assert app_config.label == "django_migration_fixture"

models = set()
for obj in get_objects():
obj.save()
models.add(obj.object._meta.model)

reset_db_sequences(models)

# Disconnect the signal, otherwise we might be called during
# e.g. flush (in tests) again.
signals.post_migrate.disconnect(signal_handler, weak=False)

signals.post_migrate.connect(signal_handler, weak=False)

def unload_fixture(apps, schema_editor):
for obj in get_objects():
Expand All @@ -55,4 +90,4 @@ def unload_fixture(apps, schema_editor):
if not raise_does_not_exist:
raise FixtureObjectDoesNotExist("Model %s instance with kwargs %s does not exist." % (model, kwargs))

return dict(code=load_fixture, reverse_code=unload_fixture)
return dict(code=load_fixture, reverse_code=unload_fixture)
2 changes: 2 additions & 0 deletions django_migration_fixture/migrations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Empty fake migration module to make Django consider us for the `post_migrate`
# signal.
1 change: 1 addition & 0 deletions django_migration_fixture/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Make Django consider us for the `post_migrate` signal.