ProjectDjango/Project.py

changeset 125
d280acf98fb5
parent 122
eb1311184f6f
child 132
576cb5a3b035
equal deleted inserted replaced
124:5c925935cbb9 125:d280acf98fb5
95 class Project(QObject): 95 class Project(QObject):
96 """ 96 """
97 Class implementing the Django project support. 97 Class implementing the Django project support.
98 """ 98 """
99 RecentApplicationsKey = "Django/RecentApplications" 99 RecentApplicationsKey = "Django/RecentApplications"
100 RecentDatabaseNamesKey = "Django/RecentDatabaseNames"
100 101
101 def __init__(self, plugin, parent=None): 102 def __init__(self, plugin, parent=None):
102 """ 103 """
103 Constructor 104 Constructor
104 105
117 self.__serverProc = None 118 self.__serverProc = None
118 self.__testServerProc = None 119 self.__testServerProc = None
119 120
120 self.__recentApplications = [] 121 self.__recentApplications = []
121 self.__loadRecentApplications() 122 self.__loadRecentApplications()
123
124 self.__recentDatabaseNames = []
125 self.__loadRecentDatabaseNames()
122 126
123 self.__recentTestData = { 127 self.__recentTestData = {
124 "RecentTestLabels": [], 128 "RecentTestLabels": [],
125 "RecentTestTags": [], 129 "RecentTestTags": [],
126 "RecentTestExcludeTags": [], 130 "RecentTestExcludeTags": [],
319 323
320 def __initDatabaseActions(self): 324 def __initDatabaseActions(self):
321 """ 325 """
322 Private method to define the database related actions. 326 Private method to define the database related actions.
323 """ 327 """
328 self.selectDatabaseNameAct = E5Action(
329 self.tr('Current Database'),
330 "",
331 0, 0,
332 self, 'django_current_database')
333 self.selectDatabaseNameAct.setStatusTip(self.tr(
334 'Selects the current database'))
335 self.selectDatabaseNameAct.setWhatsThis(self.tr(
336 """<b>Current Database</b>"""
337 """<p>Selects the database name to be used by all database"""
338 """ actions. An empty database name indicates to use the default"""
339 """ name.</p>"""
340 ))
341 self.selectDatabaseNameAct.triggered.connect(self.__selectDatabaseName)
342 self.actions.append(self.selectDatabaseNameAct)
343 self.__setCurrentDatabase(None)
344
324 self.inspectDatabaseAct = E5Action( 345 self.inspectDatabaseAct = E5Action(
325 self.tr('Introspect'), 346 self.tr('Introspect'),
326 self.tr('&Introspect'), 347 self.tr('&Introspect'),
327 0, 0, 348 0, 0,
328 self, 'django_database_inspect') 349 self, 'django_database_inspect')
570 """<b>Start Python Console</b>""" 591 """<b>Start Python Console</b>"""
571 """<p>Starts a Python interactive interpreter.</p>""" 592 """<p>Starts a Python interactive interpreter.</p>"""
572 )) 593 ))
573 self.runPythonShellAct.triggered.connect(self.__runPythonShell) 594 self.runPythonShellAct.triggered.connect(self.__runPythonShell)
574 self.actions.append(self.runPythonShellAct) 595 self.actions.append(self.runPythonShellAct)
596
597 self.testEmailAct = E5Action(
598 self.tr('Send Test Email'),
599 self.tr('Send Test &Email'),
600 0, 0,
601 self, 'django_tools_sendtestemail')
602 self.testEmailAct.setStatusTip(self.tr(
603 'Send a test email through Django'))
604 self.testEmailAct.setWhatsThis(self.tr(
605 """<b>Send Test Email</b>"""
606 """<p>Sends a test email to confirm email sending through Django"""
607 """ is working.</p>"""
608 ))
609 self.testEmailAct.triggered.connect(self.__sendTestEmail)
610 self.actions.append(self.testEmailAct)
575 611
576 def __initTestingActions(self): 612 def __initTestingActions(self):
577 """ 613 """
578 Private method to define the testing actions. 614 Private method to define the testing actions.
579 """ 615 """
861 @rtype QMenu 897 @rtype QMenu
862 """ 898 """
863 menu = QMenu(self.tr("&Database"), self.__ui) 899 menu = QMenu(self.tr("&Database"), self.__ui)
864 menu.setTearOffEnabled(True) 900 menu.setTearOffEnabled(True)
865 901
902 menu.addAction(self.selectDatabaseNameAct)
903 menu.addSeparator()
866 menu.addAction(self.inspectDatabaseAct) 904 menu.addAction(self.inspectDatabaseAct)
867 menu.addSeparator() 905 menu.addSeparator()
868 menu.addAction(self.flushDatabaseAct) 906 menu.addAction(self.flushDatabaseAct)
869 menu.addSeparator() 907 menu.addSeparator()
870 menu.addAction(self.databaseClientAct) 908 menu.addAction(self.databaseClientAct)
941 menu.setTearOffEnabled(True) 979 menu.setTearOffEnabled(True)
942 980
943 menu.addAction(self.diffSettingsAct) 981 menu.addAction(self.diffSettingsAct)
944 menu.addSeparator() 982 menu.addSeparator()
945 menu.addAction(self.runPythonShellAct) 983 menu.addAction(self.runPythonShellAct)
984 if self.getDjangoVersion() >= (1, 9, 0):
985 menu.addSeparator()
986 menu.addAction(self.testEmailAct)
946 987
947 self.__menus["tools"] = menu 988 self.__menus["tools"] = menu
948 989
949 return menu 990 return menu
950 991
1358 else: 1399 else:
1359 cmd = "" 1400 cmd = ""
1360 else: 1401 else:
1361 if language == "Python2": 1402 if language == "Python2":
1362 cmds = ["django-admin2.py", "django-admin2", 1403 cmds = ["django-admin2.py", "django-admin2",
1363 "django-admin.py-2.7", "django-admin.py-2.6"] 1404 "django-admin.py-2.7", "django-admin.py-2.6"
1405 ]
1364 elif language == "Python3": 1406 elif language == "Python3":
1365 cmds = ["django-admin3.py", "django-admin3", 1407 cmds = ["django-admin3.py", "django-admin3",
1366 "django-admin.py-3.6", "django-admin.py-3.5", 1408 "django-admin.py-3.7", "django-admin.py-3.6",
1367 "django-admin.py-3.4", "django-admin.py-3.3", 1409 "django-admin.py-3.5", "django-admin.py-3.4",
1368 "django-admin.py-3.2"] 1410 "django-admin.py-3.3", "django-admin.py-3.2",
1411 ]
1369 else: 1412 else:
1370 cmds = [] 1413 cmds = []
1371 cmds.extend(["django-admin.py", "django-admin"]) 1414 cmds.extend(["django-admin.py", "django-admin"])
1372 for cmd in cmds: 1415 for cmd in cmds:
1373 if Utilities.isinpath(cmd): 1416 if Utilities.isinpath(cmd):
2026 args.append(self.__getPythonExecutable()) 2069 args.append(self.__getPythonExecutable())
2027 args.append("manage.py") 2070 args.append("manage.py")
2028 args.append("runserver") 2071 args.append("runserver")
2029 if self.__plugin.getPreferences("UseIPv6"): 2072 if self.__plugin.getPreferences("UseIPv6"):
2030 args.append("--ipv6") 2073 args.append("--ipv6")
2031 # TODO: add support for --nothreading 2074 if not self.__plugin.getPreferences("UseThreading"):
2075 args.append("--nothreading")
2032 addr = self.__plugin.getPreferences("ServerAddress") 2076 addr = self.__plugin.getPreferences("ServerAddress")
2033 if addr: 2077 if addr:
2034 args.append(addr) 2078 args.append(addr)
2035 2079
2036 try: 2080 try:
2101 ' url "{0}".').format(url.toString())) 2145 ' url "{0}".').format(url.toString()))
2102 else: 2146 else:
2103 self.__ui.launchHelpViewer(url) 2147 self.__ui.launchHelpViewer(url)
2104 2148
2105 ################################################################## 2149 ##################################################################
2150 ## slots below implement functions to save and load recently used
2151 ## database names
2152 ##################################################################
2153
2154 def __loadRecentDatabaseNames(self):
2155 """
2156 Private method to load the list of recently used database names.
2157 """
2158 self.__recentDatabaseNames = [""]
2159 Preferences.Prefs.rsettings.sync()
2160 rdb = Preferences.Prefs.rsettings.value(self.RecentDatabaseNamesKey)
2161 if rdb is not None:
2162 maxRecentDatabaseNames = \
2163 self.__plugin.getPreferences("RecentNumberDatabaseNames")
2164 self.__recentDatabaseNames = rdb[:maxRecentDatabaseNames]
2165
2166 def __saveRecentDatabaseNames(self):
2167 """
2168 Private method to save the list of recently used database names.
2169 """
2170 Preferences.Prefs.rsettings.setValue(self.RecentDatabaseNamesKey,
2171 self.__recentDatabaseNames)
2172 Preferences.Prefs.rsettings.sync()
2173
2174 def getRecentDatabaseNames(self):
2175 """
2176 Public method to get the list of recently used database names.
2177
2178 @return list of recently used database names
2179 @rtype list of str
2180 """
2181 self.__loadRecentDatabaseNames()
2182 return self.__recentDatabaseNames
2183
2184 def setMostRecentDatabaseNames(self, dbName):
2185 """
2186 Public method to set the most recently used database names.
2187
2188 @param dbName database name
2189 @type str
2190 """
2191 if dbName in self.__recentDatabaseNames:
2192 self.__recentDatabaseNames.remove(dbName)
2193 self.__recentDatabaseNames.insert(0, dbName)
2194
2195 maxRecentDatabaseNames = \
2196 self.__plugin.getPreferences("RecentNumberDatabaseNames")
2197 if len(self.__recentDatabaseNames) > maxRecentDatabaseNames:
2198 self.__recentDatabaseNames = \
2199 self.__recentDatabaseNames[:maxRecentDatabaseNames]
2200 self.__saveRecentDatabaseNames()
2201
2202 def __selectDatabaseName(self):
2203 """
2204 Private method to select the name of the database to work with.
2205 """
2206 recentDatabases = self.getRecentDatabaseNames()[:]
2207 if "" not in recentDatabases:
2208 recentDatabases.insert(1, "")
2209
2210 selectedDatabase, ok = QInputDialog.getItem(
2211 self.__ui,
2212 self.tr("Database Name"),
2213 self.tr("Select a database name (leave empty for default):"),
2214 recentDatabases,
2215 0, True)
2216
2217 if ok:
2218 self.setMostRecentDatabaseNames(selectedDatabase)
2219 self.__setCurrentDatabase(selectedDatabase)
2220
2221 def __setCurrentDatabase(self, database):
2222 """
2223 Private method to set the database name to be used.
2224
2225 @param database name of the database
2226 @type str
2227 """
2228 if database is None:
2229 database = self.getRecentDatabaseNames()[0]
2230
2231 self.__currentDatabase = database
2232 if database:
2233 curDb = database
2234 else:
2235 curDb = self.tr("<default>")
2236 self.selectDatabaseNameAct.setText(
2237 self.tr('&Current Database ({0})').format(curDb))
2238
2239 def currentDatabase(self):
2240 """
2241 Public method to get the database name to be used.
2242
2243 @return database name
2244 @rtype str
2245 """
2246 return self.__currentDatabase
2247
2248 ##################################################################
2106 ## slots below implement database related functions 2249 ## slots below implement database related functions
2107 ################################################################## 2250 ##################################################################
2108 2251
2109 def __databaseInspect(self): 2252 def __databaseInspect(self):
2110 """ 2253 """
2115 2258
2116 args = [] 2259 args = []
2117 args.append(self.__getPythonExecutable()) 2260 args.append(self.__getPythonExecutable())
2118 args.append("manage.py") 2261 args.append("manage.py")
2119 args.append("inspectdb") 2262 args.append("inspectdb")
2120 # TODO: add support for --database DATABASE for Django 1.9.0+ 2263 if self.__currentDatabase:
2264 args.append("--database={0}".format(self.__currentDatabase))
2121 2265
2122 try: 2266 try:
2123 path = self.__sitePath() 2267 path = self.__sitePath()
2124 except DjangoNoSiteSelectedException: 2268 except DjangoNoSiteSelectedException:
2125 return 2269 return
2150 args = [] 2294 args = []
2151 args.append(self.__getPythonExecutable()) 2295 args.append(self.__getPythonExecutable())
2152 args.append("manage.py") 2296 args.append("manage.py")
2153 args.append("flush") 2297 args.append("flush")
2154 args.append("--noinput") 2298 args.append("--noinput")
2155 # TODO: add support for --database DATABASE for Django 1.9.0+ 2299 if self.__currentDatabase:
2300 args.append("--database={0}".format(self.__currentDatabase))
2156 2301
2157 dia = DjangoDialog( 2302 dia = DjangoDialog(
2158 title, 2303 title,
2159 msgSuccess=self.tr("Database tables flushed" 2304 msgSuccess=self.tr("Database tables flushed"
2160 " successfully.")) 2305 " successfully."))
2172 args = Utilities.parseOptionString(consoleCmd) 2317 args = Utilities.parseOptionString(consoleCmd)
2173 args[0] = Utilities.getExecutablePath(args[0]) 2318 args[0] = Utilities.getExecutablePath(args[0])
2174 args.append(self.__getPythonExecutable()) 2319 args.append(self.__getPythonExecutable())
2175 args.append("manage.py") 2320 args.append("manage.py")
2176 args.append("dbshell") 2321 args.append("dbshell")
2177 # TODO: add support for --database DATABASE for Django 1.9.0+ 2322 if self.__currentDatabase:
2323 args.append("--database={0}".format(self.__currentDatabase))
2178 try: 2324 try:
2179 wd = self.__sitePath() 2325 wd = self.__sitePath()
2180 self.__adjustWorkingDirectory(args, wd) 2326 self.__adjustWorkingDirectory(args, wd)
2181 started, pid = QProcess.startDetached(args[0], args[1:], wd) 2327 started, pid = QProcess.startDetached(args[0], args[1:], wd)
2182 if not started: 2328 if not started:
2214 2360
2215 args = [] 2361 args = []
2216 args.append(self.__getPythonExecutable()) 2362 args.append(self.__getPythonExecutable())
2217 args.append("manage.py") 2363 args.append("manage.py")
2218 args.append(command) 2364 args.append(command)
2219 # TODO: add support for --database DATABASE for Django 1.9.0+ 2365 if self.__currentDatabase:
2366 args.append("--database={0}".format(self.__currentDatabase))
2220 args += apps 2367 args += apps
2221 2368
2222 fileFilter = self.tr("SQL Files (*.sql)") 2369 fileFilter = self.tr("SQL Files (*.sql)")
2223 2370
2224 dia = DjangoDialog(title, fixed=True, linewrap=False, 2371 dia = DjangoDialog(title, fixed=True, linewrap=False,
2328 2475
2329 args = [] 2476 args = []
2330 args.append(self.__getPythonExecutable()) 2477 args.append(self.__getPythonExecutable())
2331 args.append("manage.py") 2478 args.append("manage.py")
2332 args.append("sqlmigrate") 2479 args.append("sqlmigrate")
2480 if self.__currentDatabase:
2481 args.append("--database={0}".format(self.__currentDatabase))
2333 if backwards: 2482 if backwards:
2334 args.append("--backwards") 2483 args.append("--backwards")
2335 # TODO: add support for --database DATABASE for Django 1.9.0+
2336 args.append(app) 2484 args.append(app)
2337 args.append(migration) 2485 args.append(migration)
2338 2486
2339 fileFilter = self.tr("SQL Files (*.sql)") 2487 fileFilter = self.tr("SQL Files (*.sql)")
2340 2488
2359 2507
2360 from .DjangoMigrationsListDialog import DjangoMigrationsListDialog 2508 from .DjangoMigrationsListDialog import DjangoMigrationsListDialog
2361 self.__migrationsListDialog = DjangoMigrationsListDialog( 2509 self.__migrationsListDialog = DjangoMigrationsListDialog(
2362 DjangoMigrationsListDialog.MigrationsListMode, self, self.__ui) 2510 DjangoMigrationsListDialog.MigrationsListMode, self, self.__ui)
2363 self.__migrationsListDialog.show() 2511 self.__migrationsListDialog.show()
2364 self.__migrationsListDialog.start(self.__getPythonExecutable(), path) 2512 self.__migrationsListDialog.start(self.__getPythonExecutable(), path,
2513 self.__currentDatabase)
2365 2514
2366 def __showMigrationsPlan(self): 2515 def __showMigrationsPlan(self):
2367 """ 2516 """
2368 Private slot to show the migrations plan. 2517 Private slot to show the migrations plan.
2369 """ 2518 """
2374 2523
2375 from .DjangoMigrationsListDialog import DjangoMigrationsListDialog 2524 from .DjangoMigrationsListDialog import DjangoMigrationsListDialog
2376 self.__migrationsPlanDialog = DjangoMigrationsListDialog( 2525 self.__migrationsPlanDialog = DjangoMigrationsListDialog(
2377 DjangoMigrationsListDialog.MigrationsPlanMode, self, self.__ui) 2526 DjangoMigrationsListDialog.MigrationsPlanMode, self, self.__ui)
2378 self.__migrationsPlanDialog.show() 2527 self.__migrationsPlanDialog.show()
2379 self.__migrationsPlanDialog.start(self.__getPythonExecutable(), path) 2528 self.__migrationsPlanDialog.start(self.__getPythonExecutable(), path,
2529 self.__currentDatabase)
2380 2530
2381 def __applyAllMigrations(self): 2531 def __applyAllMigrations(self):
2382 """ 2532 """
2383 Private slot to apply all migrations. 2533 Private slot to apply all migrations.
2384 """ 2534 """
2473 2623
2474 args = [] 2624 args = []
2475 args.append("manage.py") 2625 args.append("manage.py")
2476 args.append("showmigrations") 2626 args.append("showmigrations")
2477 args.append("--list") 2627 args.append("--list")
2478 # TODO: add support for --database DATABASE for Django 1.9.0+ 2628 if self.getDjangoVersion() >= (1, 9, 0):
2629 if self.__currentDatabase:
2630 args.append("--database={0}".format(self.__currentDatabase))
2479 2631
2480 migrations = {} 2632 migrations = {}
2481 proc = QProcess() 2633 proc = QProcess()
2482 if path: 2634 if path:
2483 proc.setWorkingDirectory(path) 2635 proc.setWorkingDirectory(path)
2507 Private slot to generate migrations for the Django project. 2659 Private slot to generate migrations for the Django project.
2508 """ 2660 """
2509 from .DjangoMakeMigrationsDialog import DjangoMakeMigrationsDialog 2661 from .DjangoMakeMigrationsDialog import DjangoMakeMigrationsDialog
2510 dlg = DjangoMakeMigrationsDialog(self.getRecentApplications()) 2662 dlg = DjangoMakeMigrationsDialog(self.getRecentApplications())
2511 if dlg.exec_() == QDialog.Accepted: 2663 if dlg.exec_() == QDialog.Accepted:
2512 apps, migration, dryRun, empty = dlg.getData() 2664 apps, migration, dryRun, empty, merge = dlg.getData()
2513 if apps: 2665 if apps:
2514 self.setMostRecentApplication(apps) 2666 self.setMostRecentApplication(apps)
2515 apps = apps.split() 2667 apps = apps.split()
2516 self.makeMigrations(apps, migration, dryRun, empty) 2668 self.makeMigrations(apps, migration, dryRun, empty, merge)
2517 2669
2518 def makeMigrations(self, apps, migration=None, dryRun=False, empty=False): 2670 def makeMigrations(self, apps, migration=None, dryRun=False, empty=False,
2671 merge=False):
2519 """ 2672 """
2520 Public method to generate migrations. 2673 Public method to generate migrations.
2521 2674
2522 @param apps list of application names to generate migrations for 2675 @param apps list of application names to generate migrations for
2523 @type list of str 2676 @type list of str
2524 @param migration name of the migration to generate 2677 @param migration name of the migration to generate
2525 @type str 2678 @type str
2526 @param dryRun flag indicating a dry run 2679 @param dryRun flag indicating a dry run
2527 @type bool 2680 @type bool
2528 @param empty flag indicating the creation of an empty migration 2681 @param empty flag indicating the creation of an empty migration
2682 @type bool
2683 @param merge flag indicating to fix migration conflicts
2529 @type bool 2684 @type bool
2530 """ 2685 """
2531 title = self.tr("Make Migrations") 2686 title = self.tr("Make Migrations")
2532 2687
2533 try: 2688 try:
2544 args.append(migration.replace(" ", "_")) 2699 args.append(migration.replace(" ", "_"))
2545 if dryRun: 2700 if dryRun:
2546 args.append("--dry-run") 2701 args.append("--dry-run")
2547 if empty: 2702 if empty:
2548 args.append("--empty") 2703 args.append("--empty")
2549 # TODO: add support for --merge (Enables fixing of migration conflicts.) 2704 if merge:
2705 args.append("--merge")
2550 if apps: 2706 if apps:
2551 args += apps 2707 args += apps
2552 2708
2553 dia = DjangoDialog(title, showInput=True) 2709 dia = DjangoDialog(title, showInput=True)
2554 res = dia.startProcess(args, path) 2710 res = dia.startProcess(args, path)
2568 return 2724 return
2569 2725
2570 from .DjangoSquashMigrationSelectionDialog import \ 2726 from .DjangoSquashMigrationSelectionDialog import \
2571 DjangoSquashMigrationSelectionDialog 2727 DjangoSquashMigrationSelectionDialog
2572 dlg = DjangoSquashMigrationSelectionDialog( 2728 dlg = DjangoSquashMigrationSelectionDialog(
2573 migrations, self.getDjangoVersion() >= (1, 9, 0)) 2729 migrations, self)
2574 if dlg.exec_() == QDialog.Accepted: 2730 if dlg.exec_() == QDialog.Accepted:
2575 app, start, end, noOptimize = dlg.getData() 2731 app, start, end, noOptimize, name = dlg.getData()
2576 2732
2577 title = self.tr("Squash Migrations") 2733 title = self.tr("Squash Migrations")
2578 2734
2579 try: 2735 try:
2580 path = self.__sitePath() 2736 path = self.__sitePath()
2581 except DjangoNoSiteSelectedException: 2737 except DjangoNoSiteSelectedException:
2582 return 2738 return
2583 2739
2584 args = [] 2740 args = []
2585 args.append(self.__getPythonExecutable()) 2741 args.append(self.__getPythonExecutable())
2586 args.append("manage.py") 2742 args.append("manage.py")
2587 args.append("squashmigrations") 2743 args.append("squashmigrations")
2588 args.append("--noinput") 2744 args.append("--noinput")
2589 if noOptimize: 2745 if noOptimize:
2590 args.append("--no-optimize") 2746 args.append("--no-optimize")
2591 # TODO: add --squashed-name SQUASHED_NAME for Django 2.0.0+ 2747 if name:
2592 args.append(app) 2748 args.append("--squashed-name={0}".format(name))
2593 if start: 2749 args.append(app)
2594 args.append(start) 2750 if start:
2595 args.append(end) 2751 args.append(start)
2596 2752 args.append(end)
2597 dia = DjangoDialog(title) 2753
2598 res = dia.startProcess(args, path) 2754 dia = DjangoDialog(title)
2599 if res: 2755 res = dia.startProcess(args, path)
2600 dia.exec_() 2756 if res:
2757 dia.exec_()
2601 2758
2602 ################################################################## 2759 ##################################################################
2603 ## slots below implement some tool functions 2760 ## slots below implement some tool functions
2604 ################################################################## 2761 ##################################################################
2605 2762
2607 """ 2764 """
2608 Private slot to show the changes made to the settings.py file. 2765 Private slot to show the changes made to the settings.py file.
2609 """ 2766 """
2610 title = self.tr("Diff Settings") 2767 title = self.tr("Diff Settings")
2611 2768
2612 args = [] 2769 from .DjangoDiffsettingsDataDialog import DjangoDiffsettingsDataDialog
2613 args.append(self.__getPythonExecutable()) 2770 dlg = DjangoDiffsettingsDataDialog(self, self.__ui)
2614 args.append("manage.py") 2771 if dlg.exec_() == QDialog.Accepted:
2615 args.append("diffsettings") 2772 showAll, defaultModule, outputFormat = dlg.getData()
2616 # TODO: add support for --default MODULE as of Django 1.11.0 2773
2617 # TODO: add support for --output {hash,unified} as of Django 2.0.0 2774 args = []
2618 # with hash being the default 2775 args.append(self.__getPythonExecutable())
2619 2776 args.append("manage.py")
2620 try: 2777 args.append("diffsettings")
2621 path = self.__sitePath() 2778 if showAll:
2622 except DjangoNoSiteSelectedException: 2779 args.append("--all")
2623 return 2780 if defaultModule:
2624 2781 args.append("--default={0}".format(defaultModule))
2625 dia = DjangoDialog(title, fixed=True, linewrap=False) 2782 if outputFormat:
2626 res = dia.startProcess(args, path, False) 2783 args.append("--output={0}".format(outputFormat))
2627 if res: 2784
2628 dia.exec_() 2785 try:
2786 path = self.__sitePath()
2787 except DjangoNoSiteSelectedException:
2788 return
2789
2790 dia = DjangoDialog(title, fixed=True, linewrap=False)
2791 res = dia.startProcess(args, path, False)
2792 if res:
2793 dia.exec_()
2629 2794
2630 def __runPythonShell(self): 2795 def __runPythonShell(self):
2631 """ 2796 """
2632 Private slot to start a Python console for a Django project. 2797 Private slot to start a Python console for a Django project.
2633 """ 2798 """
2638 args[0] = Utilities.getExecutablePath(args[0]) 2803 args[0] = Utilities.getExecutablePath(args[0])
2639 args.append(self.__getPythonExecutable()) 2804 args.append(self.__getPythonExecutable())
2640 args.append("manage.py") 2805 args.append("manage.py")
2641 args.append("shell") 2806 args.append("shell")
2642 language = self.__e5project.getProjectLanguage() 2807 language = self.__e5project.getProjectLanguage()
2643 # TODO: add support for --interface {ipython,bpython,python} as of Djanngo 1.10.0
2644 # TODO: don't use this for Django 1.10.0+
2645 if language == "Python2": 2808 if language == "Python2":
2646 if self.__plugin.getPreferences("UsePlainPythonPy2"): 2809 if self.getDjangoVersion() < (1, 10, 0):
2647 args.append("--plain") 2810 if (self.__plugin.getPreferences("Python2ConsoleType") ==
2811 "python"):
2812 args.append("--plain")
2813 else:
2814 args.append("--interface={0}".format(
2815 self.__plugin.getPreferences("Python2ConsoleType")))
2648 else: 2816 else:
2649 if self.__plugin.getPreferences("UsePlainPythonPy3"): 2817 if self.getDjangoVersion() < (1, 10, 0):
2650 args.append("--plain") 2818 if (self.__plugin.getPreferences("Python3ConsoleType") ==
2819 "python"):
2820 args.append("--plain")
2821 else:
2822 args.append("--interface={0}".format(
2823 self.__plugin.getPreferences("Python3ConsoleType")))
2651 try: 2824 try:
2652 wd = self.__sitePath() 2825 wd = self.__sitePath()
2653 self.__adjustWorkingDirectory(args, wd) 2826 self.__adjustWorkingDirectory(args, wd)
2654 started, pid = QProcess.startDetached(args[0], args[1:], wd) 2827 started, pid = QProcess.startDetached(args[0], args[1:], wd)
2655 if not started: 2828 if not started:
2658 self.tr('Process Generation Error'), 2831 self.tr('Process Generation Error'),
2659 self.tr('The Django process could not be started.')) 2832 self.tr('The Django process could not be started.'))
2660 except DjangoNoSiteSelectedException: 2833 except DjangoNoSiteSelectedException:
2661 pass 2834 pass
2662 2835
2836 def __sendTestEmail(self):
2837 """
2838 Private slot to send a test email through Django.
2839 """
2840 if self.getDjangoVersion() < (1, 9, 0):
2841 return
2842
2843 title = self.tr("Send Test Email")
2844
2845 from .DjangoSendTestEmailDataDialog import \
2846 DjangoSendTestEmailDataDialog
2847 dlg = DjangoSendTestEmailDataDialog(self.__ui)
2848 if dlg.exec_() == QDialog.Accepted:
2849 managers, admins, recipients = dlg.getData()
2850
2851 args = []
2852 args.append(self.__getPythonExecutable())
2853 args.append("manage.py")
2854 args.append("sendtestemail")
2855 if managers:
2856 args.append("--managers")
2857 if admins:
2858 args.append("--admins")
2859 args.extend(recipients)
2860
2861 try:
2862 path = self.__sitePath()
2863 except DjangoNoSiteSelectedException:
2864 return
2865
2866 dia = DjangoDialog(
2867 title,
2868 linewrap=False,
2869 msgSuccess=self.tr("Test Email sent successfully."),
2870 msgError=self.tr("Test Email could not be sent.")
2871 )
2872 res = dia.startProcess(args, path, False)
2873 if res:
2874 dia.exec_()
2875
2663 ################################################################## 2876 ##################################################################
2664 ## slots below implement caching functions 2877 ## slots below implement caching functions
2665 ################################################################## 2878 ##################################################################
2666 2879
2667 def __createCacheTables(self): 2880 def __createCacheTables(self):
2668 """ 2881 """
2669 Private slot to create the tables for the SQL caching backend. 2882 Private slot to create the tables for the SQL caching backend.
2670 """ 2883 """
2671 # TODO: this doesn't need the tables anymore
2672 # TODO: add support for the --database DATABASE option for Django 1.9.0+
2673 title = self.tr("Create Cache Tables") 2884 title = self.tr("Create Cache Tables")
2674 2885
2675 try: 2886 try:
2676 wd = self.__sitePath() 2887 wd = self.__sitePath()
2677 except DjangoNoSiteSelectedException: 2888 except DjangoNoSiteSelectedException:
2678 return 2889 return
2679 2890
2680 tblStr, ok = QInputDialog.getText( 2891 args = []
2681 self.__ui, 2892 args.append(self.__getPythonExecutable())
2893 args.append("manage.py")
2894 args.append("createcachetable")
2895 if self.__currentDatabase:
2896 args.append("--database={0}".format(self.__currentDatabase))
2897
2898 dia = DjangoDialog(
2682 title, 2899 title,
2683 self.tr("Enter the names of the cache tables separated by" 2900 msgSuccess=self.tr("Cache tables created successfully."))
2684 " spaces."), 2901 res = dia.startProcess(args, wd)
2685 QLineEdit.Normal) 2902 if res:
2686 if ok and tblStr != "": 2903 dia.exec_()
2687 tableNames = tblStr.split()
2688
2689 args = []
2690 args.append(self.__getPythonExecutable())
2691 args.append("manage.py")
2692 args.append("createcachetable")
2693 args += tableNames
2694
2695 dia = DjangoDialog(
2696 title,
2697 msgSuccess=self.tr("Cache tables created successfully."))
2698 res = dia.startProcess(args, wd)
2699 if res:
2700 dia.exec_()
2701 2904
2702 ################################################################## 2905 ##################################################################
2703 ## slots below implement testing functions 2906 ## slots below implement testing functions
2704 ################################################################## 2907 ##################################################################
2705 2908
2725 args.append("dumpdata") 2928 args.append("dumpdata")
2726 args.append("--format={0}".format(dumpFormat)) 2929 args.append("--format={0}".format(dumpFormat))
2727 args.append("--indent={0}".format(indent)) 2930 args.append("--indent={0}".format(indent))
2728 for excl in excls: 2931 for excl in excls:
2729 args.append("--exclude={0}".format(excl)) 2932 args.append("--exclude={0}".format(excl))
2730 # TODO: add support for --database DATABASE for Django 1.9.0+ 2933 if self.getDjangoVersion() >= (1, 9, 0):
2934 if self.__currentDatabase:
2935 args.append("--database={0}".format(
2936 self.__currentDatabase))
2731 args += appls 2937 args += appls
2732 2938
2733 if dumpFormat == "json": 2939 if dumpFormat == "json":
2734 fileFilters = self.tr("JSON Files (*.json)") 2940 fileFilters = self.tr("JSON Files (*.json)")
2735 elif dumpFormat == "xml": 2941 elif dumpFormat == "xml":
2752 try: 2958 try:
2753 wd = self.__sitePath() 2959 wd = self.__sitePath()
2754 except DjangoNoSiteSelectedException: 2960 except DjangoNoSiteSelectedException:
2755 return 2961 return
2756 2962
2757 # TODO: use the old DjangoLoaddataDataDialog for __runTestServer before modifying this
2758 from .DjangoLoaddataDataDialog import DjangoLoaddataDataDialog 2963 from .DjangoLoaddataDataDialog import DjangoLoaddataDataDialog
2759 dlg = DjangoLoaddataDataDialog(self, self.__ui) 2964 dlg = DjangoLoaddataDataDialog(self, self.__ui)
2760 if dlg.exec_() == QDialog.Accepted: 2965 if dlg.exec_() == QDialog.Accepted:
2761 fixtures = dlg.getData() 2966 fixtures, excludes, appLabel, ignore = dlg.getData()
2762 2967
2763 args = [] 2968 args = []
2764 args.append(self.__getPythonExecutable()) 2969 args.append(self.__getPythonExecutable())
2765 args.append("manage.py") 2970 args.append("manage.py")
2766 args.append("loaddata") 2971 args.append("loaddata")
2767 # TODO: add support for --exclude EXCLUDE as of Django 1.11.0 2972 if self.getDjangoVersion() >= (1, 11, 0):
2768 # TODO: add support for --ignorenonexistent 2973 for excl in excludes:
2769 # TODO: add support for --database DATABASE for Django 1.9.0+ 2974 args.append("--exclude={0}".format(excl))
2770 # TODO: add support for --app APP_LABEL 2975 if ignore:
2976 args.append("--ignorenonexistent")
2977 if appLabel:
2978 args.append("--app={0}".format(appLabel))
2979 if self.__currentDatabase:
2980 args.append("--database={0}".format(self.__currentDatabase))
2771 args += fixtures 2981 args += fixtures
2772 2982
2773 dia = DjangoDialog(title) 2983 dia = DjangoDialog(title)
2774 res = dia.startProcess(args, wd) 2984 res = dia.startProcess(args, wd)
2775 if res: 2985 if res:
2833 fixtures. 3043 fixtures.
2834 """ 3044 """
2835 consoleCmd = self.__isSpawningConsole( 3045 consoleCmd = self.__isSpawningConsole(
2836 self.__plugin.getPreferences("ConsoleCommand"))[1] 3046 self.__plugin.getPreferences("ConsoleCommand"))[1]
2837 if consoleCmd: 3047 if consoleCmd:
2838 # TODO: use the old DjangoLoaddataDataDialog for this 3048 from .DjangoRunTestServerDataDialog import \
2839 from .DjangoLoaddataDataDialog import DjangoLoaddataDataDialog 3049 DjangoRunTestServerDataDialog
2840 dlg = DjangoLoaddataDataDialog(self, self.__ui) 3050 dlg = DjangoRunTestServerDataDialog(self, self.__ui)
2841 if dlg.exec_() == QDialog.Accepted: 3051 if dlg.exec_() == QDialog.Accepted:
2842 fixtures = dlg.getData() 3052 fixtures = dlg.getData()
2843 3053
2844 args = Utilities.parseOptionString(consoleCmd) 3054 args = Utilities.parseOptionString(consoleCmd)
2845 args[0] = Utilities.getExecutablePath(args[0]) 3055 args[0] = Utilities.getExecutablePath(args[0])
3044 3254
3045 args = [] 3255 args = []
3046 args.append(self.__getPythonExecutable()) 3256 args.append(self.__getPythonExecutable())
3047 args.append("manage.py") 3257 args.append("manage.py")
3048 args.append("makemessages") 3258 args.append("makemessages")
3049 # TODO: rename this --locale 3259 args.append("--locale={0}".format(code))
3050 args.append("-l")
3051 args.append(code)
3052 3260
3053 try: 3261 try:
3054 wd = self.__sitePath() 3262 wd = self.__sitePath()
3055 except DjangoNoSiteSelectedException: 3263 except DjangoNoSiteSelectedException:
3056 E5MessageBox.warning( 3264 E5MessageBox.warning(
3098 if locale: 3306 if locale:
3099 args = [] 3307 args = []
3100 args.append(self.__getPythonExecutable()) 3308 args.append(self.__getPythonExecutable())
3101 args.append("manage.py") 3309 args.append("manage.py")
3102 args.append("makemessages") 3310 args.append("makemessages")
3103 # TODO: this seems to be not supported anymore
3104 args.append("--no-obsolete") 3311 args.append("--no-obsolete")
3105 # TODO: rename this --locale 3312 args.append("--locale={0}".format(locale))
3106 args.append("-l")
3107 args.append(locale)
3108 argsLists.append(args) 3313 argsLists.append(args)
3109 3314
3110 if len(argsLists) == 0: 3315 if len(argsLists) == 0:
3111 E5MessageBox.warning( 3316 E5MessageBox.warning(
3112 None, 3317 None,
3148 if locale: 3353 if locale:
3149 args = [] 3354 args = []
3150 args.append(self.__getPythonExecutable()) 3355 args.append(self.__getPythonExecutable())
3151 args.append("manage.py") 3356 args.append("manage.py")
3152 args.append("makemessages") 3357 args.append("makemessages")
3153 # TODO: rename this --locale 3358 args.append("--locale={0}".format(locale))
3154 args.append("-l")
3155 args.append(locale)
3156 argsLists.append(args) 3359 argsLists.append(args)
3157 3360
3158 if len(argsLists) == 0: 3361 if len(argsLists) == 0:
3159 E5MessageBox.warning( 3362 E5MessageBox.warning(
3160 None, 3363 None,
3179 3382
3180 args = [] 3383 args = []
3181 args.append(self.__getPythonExecutable()) 3384 args.append(self.__getPythonExecutable())
3182 args.append("manage.py") 3385 args.append("manage.py")
3183 args.append("makemessages") 3386 args.append("makemessages")
3184 args.append("-a") 3387 args.append("--all")
3185 # TODO: this seems to be not supported anymore
3186 args.append("--no-obsolete") 3388 args.append("--no-obsolete")
3187 3389
3188 try: 3390 try:
3189 wd = self.__sitePath() 3391 wd = self.__sitePath()
3190 except DjangoNoSiteSelectedException: 3392 except DjangoNoSiteSelectedException:
3213 3415
3214 args = [] 3416 args = []
3215 args.append(self.__getPythonExecutable()) 3417 args.append(self.__getPythonExecutable())
3216 args.append("manage.py") 3418 args.append("manage.py")
3217 args.append("makemessages") 3419 args.append("makemessages")
3218 args.append("-a") 3420 args.append("--all")
3219 3421
3220 try: 3422 try:
3221 wd = self.__sitePath() 3423 wd = self.__sitePath()
3222 except DjangoNoSiteSelectedException: 3424 except DjangoNoSiteSelectedException:
3223 E5MessageBox.warning( 3425 E5MessageBox.warning(
3260 if locale: 3462 if locale:
3261 args = [] 3463 args = []
3262 args.append(self.__getPythonExecutable()) 3464 args.append(self.__getPythonExecutable())
3263 args.append("manage.py") 3465 args.append("manage.py")
3264 args.append("compilemessages") 3466 args.append("compilemessages")
3265 args.append("-l") 3467 args.append("--locale={0}".format(locale))
3266 args.append(locale) 3468 if self.getDjangoVersion() >= (1, 8, 0):
3267 # TODO: add support for --use-fuzzy per Preferences 3469 if self.__plugin.getPreferences("FuzzyTranslations"):
3470 args.append("--use-fuzzy")
3268 argsLists.append(args) 3471 argsLists.append(args)
3269 3472
3270 if len(argsLists) == 0: 3473 if len(argsLists) == 0:
3271 E5MessageBox.warning( 3474 E5MessageBox.warning(
3272 None, 3475 None,
3298 3501
3299 args = [] 3502 args = []
3300 args.append(self.__getPythonExecutable()) 3503 args.append(self.__getPythonExecutable())
3301 args.append("manage.py") 3504 args.append("manage.py")
3302 args.append("compilemessages") 3505 args.append("compilemessages")
3303 # TODO: add support for --use-fuzzy per Preferences 3506 if self.getDjangoVersion() >= (1, 8, 0):
3507 if self.__plugin.getPreferences("FuzzyTranslations"):
3508 args.append("--use-fuzzy")
3304 3509
3305 try: 3510 try:
3306 wd = self.__sitePath() 3511 wd = self.__sitePath()
3307 except DjangoNoSiteSelectedException: 3512 except DjangoNoSiteSelectedException:
3308 E5MessageBox.warning( 3513 E5MessageBox.warning(
3387 3592
3388 dia = DjangoDialog(self.tr("Check Project")) 3593 dia = DjangoDialog(self.tr("Check Project"))
3389 res = dia.startProcess(args, path, mergedOutput=True) 3594 res = dia.startProcess(args, path, mergedOutput=True)
3390 if res: 3595 if res:
3391 dia.exec_() 3596 dia.exec_()
3392
3393 # TODO: add support for sendtestemail for Django 1.9.0+
3394 # sendtestemail [email [email ...]]
3395 # --managers Mails the email addresses specified in MANAGERS using mail_managers().
3396 # --admins Mails the email addresses specified in ADMINS using mail_admins().

eric ide

mercurial