ProjectDjango/Project.py

changeset 73
8a4ccc4f1359
parent 72
0f95786f7868
child 75
0165ce437462
--- a/ProjectDjango/Project.py	Sat Dec 17 19:07:02 2016 +0100
+++ b/ProjectDjango/Project.py	Mon Dec 19 18:44:07 2016 +0100
@@ -657,7 +657,6 @@
         """
         Private method to define the migration actions.
         """
-        # TODO: showmigrations
         self.showMigrationsAct = E5Action(
             self.tr('Show Migrations'),
             self.tr('&Show Migrations'),
@@ -688,9 +687,68 @@
         self.showMigrationsPlanAct.triggered.connect(self.__showMigrationsPlan)
         self.actions.append(self.showMigrationsPlanAct)
         
-        # TODO: makemigrations
-        # TODO: migrate
+        self.migrateAllAct = E5Action(
+            self.tr('Apply All Migrations'),
+            self.tr('&Apply All Migrations'),
+            0, 0,
+            self, 'django_migration_apply_all')
+        self.migrateAllAct.setStatusTip(self.tr(
+            'Apply all available migrations'))
+        self.migrateAllAct.setWhatsThis(self.tr(
+            """<b>Apply All Migrations</b>"""
+            """<p>This applies all migrations of the Django project.</p>"""
+        ))
+        self.migrateAllAct.triggered.connect(self.__applyAllMigrations)
+        self.actions.append(self.migrateAllAct)
+        
+        self.migrateSelectedAct = E5Action(
+            self.tr('Apply Selected Migrations'),
+            self.tr('Apply Selected Migrations'),
+            0, 0,
+            self, 'django_migration_apply_selected')
+        self.migrateSelectedAct.setStatusTip(self.tr(
+            'Apply selected migrations'))
+        self.migrateSelectedAct.setWhatsThis(self.tr(
+            """<b>Apply Selected Migrations</b>"""
+            """<p>This applies selected migrations of the Django"""
+            """ project.</p>"""
+        ))
+        self.migrateSelectedAct.triggered.connect(
+            self.__applySelectedMigrations)
+        self.actions.append(self.migrateSelectedAct)
+        
+        self.unmigrateAct = E5Action(
+            self.tr('Unapply Migrations'),
+            self.tr('&Unapply Migrations'),
+            0, 0,
+            self, 'django_migration_unapply')
+        self.unmigrateAct.setStatusTip(self.tr(
+            'Unapply all migrations for an app'))
+        self.unmigrateAct.setWhatsThis(self.tr(
+            """<b>Unapply Migrations</b>"""
+            """<p>This unapplies all migrations for an app of the Django"""
+            """ project.</p>"""
+        ))
+        self.unmigrateAct.triggered.connect(self.__unapplyMigrations)
+        self.actions.append(self.unmigrateAct)
+        
+        self.makeMigrationsAct = E5Action(
+            self.tr('Make Migrations'),
+            self.tr('&Make Migrations'),
+            0, 0,
+            self, 'django_migration_make')
+        self.makeMigrationsAct.setStatusTip(self.tr(
+            'Generate migrations for the project'))
+        self.makeMigrationsAct.setWhatsThis(self.tr(
+            """<b>Make Migrations</b>"""
+            """<p>This generates migrations for the Django project.</p>"""
+        ))
+        self.makeMigrationsAct.triggered.connect(self.__makeMigrations)
+        self.actions.append(self.makeMigrationsAct)
+        
         # TODO: squashmigrations
+        
+        # TODO: sqlmigrate
     
     def initMenu(self):
         """
@@ -797,6 +855,12 @@
         
         menu.addAction(self.showMigrationsAct)
         menu.addAction(self.showMigrationsPlanAct)
+        menu.addSeparator()
+        menu.addAction(self.migrateAllAct)
+        menu.addAction(self.migrateSelectedAct)
+        menu.addAction(self.unmigrateAct)
+        menu.addSeparator()
+        menu.addAction(self.makeMigrationsAct)
         
         self.__menus["migrations"] = menu
         
@@ -2082,7 +2146,7 @@
         
         from .DjangoMigrationsListDialog import DjangoMigrationsListDialog
         self.__migrationsListDialog = DjangoMigrationsListDialog(
-            DjangoMigrationsListDialog.MigrationsListMode, self.__ui)
+            DjangoMigrationsListDialog.MigrationsListMode, self, self.__ui)
         self.__migrationsListDialog.show()
         self.__migrationsListDialog.start(self.__getPythonExecutable(), path)
     
@@ -2097,10 +2161,182 @@
         
         from .DjangoMigrationsListDialog import DjangoMigrationsListDialog
         self.__migrationsPlanDialog = DjangoMigrationsListDialog(
-            DjangoMigrationsListDialog.MigrationsPlanMode, self.__ui)
+            DjangoMigrationsListDialog.MigrationsPlanMode, self, self.__ui)
         self.__migrationsPlanDialog.show()
         self.__migrationsPlanDialog.start(self.__getPythonExecutable(), path)
     
+    def __applyAllMigrations(self):
+        """
+        Public slot to apply all migrations.
+        """
+        self.applyMigrations()
+    
+    def __applySelectedMigrations(self):
+        """
+        Public slot to apply selected migrations of a selected app.
+        """
+        migrations = self.__getMigrations()
+        if not migrations:
+            E5MessageBox.information(
+                None,
+                self.tr("Apply Selected Migrations"),
+                self.tr("""No migrations available."""))
+            return
+        
+        from .DjangoMigrationSelectionDialog import \
+            DjangoMigrationSelectionDialog
+        dlg = DjangoMigrationSelectionDialog(migrations)
+        if dlg.exec_() == QDialog.Accepted:
+            app, migration = dlg.getData()
+            self.applyMigrations(app=app, migration=migration)
+    
+    def applyMigrations(self, app=None, migration=None):
+        """
+        Public slot to apply migrations.
+        
+        @param app name of an application to apply migrations for
+        @type str
+        @param migration name of a migration to update to
+        @type str
+        """
+        if migration == "zero":
+            title = self.tr("Unapply Migrations")
+        else:
+            title = self.tr("Apply Migrations")
+        
+        try:
+            path = self.__sitePath()
+        except DjangoNoSiteSelectedException:
+            return
+        
+        args = []
+        args.append(self.__getPythonExecutable())
+        args.append("manage.py")
+        args.append("migrate")
+        args.append("--noinput")
+        if app:
+            args.append(app)
+            if migration:
+                args.append(migration)
+        
+        dia = DjangoDialog(title)
+        res = dia.startProcess(args, path)
+        if res:
+            dia.exec_()
+    
+    def __unapplyMigrations(self):
+        """
+        Private slot to un-apply all migrations of an application.
+        """
+        apps = list(sorted(self.__getMigrations().keys()))
+        if not apps:
+            E5MessageBox.information(
+                None,
+                self.tr("Unapply Migrations"),
+                self.tr("""No migrations available."""))
+            return
+        
+        app, ok = QInputDialog.getItem(
+            None,
+            self.tr("Unapply Migrations"),
+            self.tr("Select an application:"),
+            [""] + apps,
+            0, False)
+        if ok and app:
+            self.applyMigrations(app=app, migration="zero")
+    
+    def __getMigrations(self):
+        """
+        Private method to get the available migrations.
+        
+        @return dictionary containing the available migrations
+        @rtype dict with app name as key (str) and list of tuples of
+            applied indication (bool) and migration name (str) as value
+        """
+        try:
+            path = self.__sitePath()
+        except DjangoNoSiteSelectedException:
+            return {}
+        
+        args = []
+        args.append("manage.py")
+        args.append("showmigrations")
+        args.append("--list")
+        
+        migrations = {}
+        proc = QProcess()
+        if path:
+            proc.setWorkingDirectory(path)
+        proc.start(self.__getPythonExecutable(), args)
+        if proc.waitForStarted():
+            if proc.waitForFinished():
+                output = str(proc.readAllStandardOutput(),
+                             Preferences.getSystem("IOEncoding"), 'replace')
+                if output:
+                    recentApp = ""
+                    for line in output.splitlines():
+                        if not line.startswith(" "):
+                            # application name
+                            recentApp = line.strip()
+                            migrations[recentApp] = []
+                        else:
+                            # migration name
+                            line = line.strip()
+                            applied = line[1] != " "
+                            name = line[3:].strip()
+                            if recentApp:
+                                migrations[recentApp].append((applied, name))
+        return migrations
+    
+    def __makeMigrations(self):
+        """
+        Private slot to generate migrations for the Django project.
+        """
+        from .DjangoMakeMigrationsDialog import DjangoMakeMigrationsDialog
+        dlg = DjangoMakeMigrationsDialog(self.getRecentApplications())
+        if dlg.exec_() == QDialog.Accepted:
+            apps, migration, dryRun = dlg.getData()
+            if apps:
+                self.setMostRecentApplication(apps)
+            apps = apps.split()
+            self.makeMigrations(apps, migration, dryRun)
+    
+    def makeMigrations(self, apps, migration=None, dryRun=False):
+        """
+        Public method to generate migrations.
+        
+        @param apps list of application names to generate migrations for
+        @type list of str
+        @param migration name of the migration to generate
+        @type str
+        @param dryRun flag indicating a dry run
+        @type bool
+        """
+        title = self.tr("Make Migrations")
+        
+        try:
+            path = self.__sitePath()
+        except DjangoNoSiteSelectedException:
+            return
+        
+        args = []
+        args.append(self.__getPythonExecutable())
+        args.append("manage.py")
+        args.append("makemigrations")
+        args.append("--noinput")
+        if migration:
+            args.append("--name")
+            args.append(migration.replace(" ", "_"))
+        if dryRun:
+            args.append("--dry-run")
+        if apps:
+            args += apps
+        
+        dia = DjangoDialog(title)
+        res = dia.startProcess(args, path)
+        if res:
+            dia.exec_()
+    
     ##################################################################
     ## slots below implement some tool functions
     ##################################################################

eric ide

mercurial