Django: Signal for "post initial migration"
Asked Answered
B

2

6

For setting up new development systems I would like to have a "post initial migration" signal.

It seems that something like this does not exist yet.

In detail: I want a signal which runs after the initial migrations have run. The second call to "manage.py migrate" should not emit this signal.

Use case: I want to set up basic data (add some users and groups, add some dummy data for "example.com", ...).

I don't want to use a migration for this, since in a migration I have only the limited model which gets returned by apps.get_model("myapp", "Country").

Same for fixtures: I don't want to use fixtures because I get my tasks done much less painful if I have the real ORM model.

Is there a way to work around it?

Banks answered 3/5, 2018 at 9:23 Comment(4)
Can you explain more about the use case?Lucia
You mean some signal when make first migrations?Hilariohilarious
@AnshulSharma I updated my question. It contains a use case now.Banks
@Hilariohilarious I updated my question. Please tell me if there is something still not clear.Banks
M
9

You could use the post_migrate signal. Check to see whether your dummy data has already been created (e.g. if User.objects.exists():) and stop if it does.

Mandrel answered 3/5, 2018 at 12:55 Comment(2)
Yes, this is a pragmatic solution. Thank youBanks
I use get_or_create() in a "post_migrate" signal handler now.Banks
L
4

@Alasdair's suggestion with the post-migrate signal sounds good, but I'll add my two cents anyways.

In past situations where I needed initial data (for example a superuser and some base config data) I used a custom admin command to assure that some initial data was present. Fixtures were not exactly achieving what I needed in those situations.

This admin command has to be idempotent in the sense that it only makes changes if the desired state is not reached yet.

For example, my ensure_auth_data command looked something like this:

class Command(BaseCommand):
    help = 'Creates superuser, permissions and groups.'

    def _ensure_superuser(self):
        u_created = False
        u_updated = False
        try:
            usr = User.objects.get(username='ralf')
        except User.DoesNotExist:
            usr = User()
            usr.username = 'ralf'
            u_created = True

        if not usr.is_active:
            usr.is_active = True
            u_updated = True
        if not usr.is_superuser:
            usr.is_superuser = True
            u_updated = True

        if u_created or u_updated:
            usr.save()

        if u_created:
            self.stdout.write('Created superuser "{}"'.format(usr.username))
        elif u_updated:
            self.stdout.write('Updated superuser "{}"'.format(usr.username))
        else:
            self.stdout.write('Superuser "{}" already up to date'.format(usr.username))

    def _ensure_permissions(self):
        # create some special permissions if they're not present

    def _ensure_groups(self):
        # create some special groups and assign them permissions

    def handle(self, *args, **options):
        self.stdout.write('Starting command')
        self.stdout.write('...')
        self._ensure_superuser()
        self.stdout.write('...')
        self._ensure_permissions()
        self.stdout.write('...')
        self._ensure_groups()
        self.stdout.write('...')
        self.stdout.write('Command finished')
Libration answered 7/5, 2018 at 23:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.