Improved settings.py to read the global settings from the .ini file.

This commit is contained in:
Tiberiu Chibici 2018-11-01 01:01:21 +02:00
parent e230f1524f
commit fc59989405
6 changed files with 309 additions and 228 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="true">
<TaskOptions isEnabled="false">
<option name="arguments" value="$FileName$ $FileNameWithoutExtension$.css --source-map" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
@ -40,7 +40,7 @@
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="program" value="scss" />
<option name="program" value="/usr/bin/scss" />
<option name="runOnExternalChanges" value="true" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="true" />

View File

@ -2,9 +2,12 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="245751b6-c863-4572-8723-8499964fe105" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/watcherTasks.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/watcherTasks.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/readme.md" beforeDir="false" afterPath="$PROJECT_DIR$/readme.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/youtube-channel-manager.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/youtube-channel-manager.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/YtManager/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/YtManager/settings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/YtManagerApp/appconfig.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/YtManagerApp/appconfig.py" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
@ -150,9 +153,9 @@
<entry key="auth_group" value="1" />
<entry key="gitignore" value="1" />
<entry key="html" value="4" />
<entry key="ini" value="5" />
<entry key="md" value="7" />
<entry key="py" value="49" />
<entry key="ini" value="7" />
<entry key="md" value="8" />
<entry key="py" value="57" />
<entry key="scss" value="2" />
<entry key="ytmanagerapp_channel" value="1" />
<entry key="ytmanagerapp_subscription" value="2" />
@ -163,20 +166,20 @@
<counts>
<entry key="Database Element" value="7" />
<entry key="HTML" value="4" />
<entry key="Ini" value="5" />
<entry key="Markdown" value="7" />
<entry key="Ini" value="7" />
<entry key="Markdown" value="8" />
<entry key="PLAIN_TEXT" value="1" />
<entry key="Python" value="49" />
<entry key="Python" value="57" />
<entry key="SCSS" value="2" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.extensions.edit">
<counts>
<entry key="Django Console" value="265" />
<entry key="Django Console" value="419" />
<entry key="html" value="12" />
<entry key="ini" value="2" />
<entry key="md" value="4844" />
<entry key="py" value="3277" />
<entry key="md" value="4881" />
<entry key="py" value="5687" />
<entry key="py@youtube-channel-manager" value="41" />
</counts>
</usages-collector>
@ -186,52 +189,67 @@
<entry key="CommandLine" value="23" />
<entry key="HTML" value="12" />
<entry key="Ini" value="2" />
<entry key="Markdown" value="4840" />
<entry key="Markdown" value="4877" />
<entry key="PLAIN_TEXT" value="18" />
<entry key="Python" value="3542" />
<entry key="Python" value="6106" />
</counts>
</usages-collector>
</session>
</component>
<component name="FileEditorManager">
<leaf>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="41" selection-start-line="41" selection-end-line="41" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/readme.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="330">
<caret line="22" column="15" lean-forward="true" selection-start-line="22" selection-start-column="15" selection-end-line="22" selection-end-column="15" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/external/pytaw/pytaw/youtube.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-11204">
<caret line="163" column="29" selection-start-line="163" selection-start-column="29" selection-end-line="163" selection-end-column="29" />
<folding>
<element signature="e#0#18#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
<splitter split-orientation="horizontal" split-proportion="0.45192307">
<split-first>
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/app/YtManager/settings.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="358">
<caret line="207" selection-start-line="207" selection-end-line="207" />
<folding>
<element signature="e#314#323#0" expanded="true" />
<marker date="1541026657396" expanded="true" signature="4447:6293" ph="..." />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file:///usr/local/lib/python3.6/dist-packages/dj_config_url.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2305">
<caret line="157" column="4" selection-start-line="157" selection-start-column="4" selection-end-line="157" selection-end-column="4" />
</state>
</provider>
</entry>
</file>
</leaf>
</split-first>
<split-second>
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/app/YtManagerApp/appconfig.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="418">
<caret line="107" lean-forward="true" selection-start-line="107" selection-end-line="107" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/config/config.ini">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" column="20" selection-start-line="13" selection-end-line="13" selection-end-column="20" />
</state>
</provider>
</entry>
</file>
</leaf>
</split-second>
</splitter>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
@ -246,8 +264,6 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>modal_update_folder</find>
<find>modal_delete_folder</find>
<find>ajax_index_get_videos</find>
<find>ajax_index_get_tree</find>
<find>self.helper</find>
@ -276,6 +292,8 @@
<find>video</find>
<find>class thum</find>
<find>DeleteS</find>
<find>dj_settings</find>
<find>is_true</find>
</findStrings>
<replaceStrings>
<replace>loading</replace>
@ -299,9 +317,6 @@
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_edit_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_update_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/management/folders.py" />
<option value="$PROJECT_DIR$/YtManagerApp/model/folder.py" />
<option value="$PROJECT_DIR$/YtManagerApp/model/subscription.py" />
<option value="$PROJECT_DIR$/YtManagerApp/model/user_settings.py" />
@ -350,6 +365,9 @@
<option value="$PROJECT_DIR$/external/pytaw/pytaw/youtube.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" />
<option value="$PROJECT_DIR$/readme.md" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/app/YtManager/settings.py" />
<option value="$PROJECT_DIR$/app/YtManagerApp/appconfig.py" />
</list>
</option>
</component>
@ -428,38 +446,25 @@
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="app" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="app" type="462c0819:PsiDirectoryNode" />
<item name="config" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="app" type="462c0819:PsiDirectoryNode" />
<item name="YtManager" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="app" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="management" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="management" type="462c0819:PsiDirectoryNode" />
<item name="jobs" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="controls" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
@ -473,11 +478,11 @@
<property name="SearchEverywhereHistoryKey" value="&#9;FILE&#9;file://D:/Dev/youtube-channel-manager/YtManager/settings.py" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="database.console.LAST_STATE" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../pytaw" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/app/YtManager/settings.py" />
<property name="list.type.of.created.stylesheet" value="SCSS" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="reference.settings.ide.settings.web.browsers" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.django.DjangoModulesConfigurable" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
@ -583,7 +588,7 @@
<env name="DJANGO_SETTINGS_MODULE" value="YtManager.settings" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
@ -638,29 +643,29 @@
<frame x="0" y="0" width="1920" height="1048" extended-state="6" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.17697228" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.17697228" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" sideWeight="0.49520257" weight="0.38152173" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.521855" visible="true" weight="0.32717392" />
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.5197228" visible="true" weight="0.32717392" />
<window_info anchor="bottom" id="Cvs" order="3" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="4" weight="0.4" />
<window_info anchor="bottom" id="Debug" order="5" sideWeight="0.49093816" weight="0.37608695" />
<window_info anchor="bottom" id="Debug" order="5" sideWeight="0.4904051" weight="0.37608695" />
<window_info anchor="bottom" id="TODO" order="6" weight="0.329718" />
<window_info anchor="bottom" id="manage.py@youtube-channel-manager" order="7" sideWeight="0.49573562" weight="0.49347827" />
<window_info anchor="bottom" id="Docker" order="8" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" order="9" weight="0.3285968" />
<window_info anchor="bottom" id="Event Log" order="10" sideWeight="0.478145" side_tool="true" visible="true" weight="0.32717392" />
<window_info anchor="bottom" id="Version Control" order="11" sideWeight="0.49840087" weight="0.15326087" />
<window_info anchor="bottom" id="Terminal" order="12" sideWeight="0.49573562" weight="0.3576087" />
<window_info anchor="bottom" id="Python Console" order="13" sideWeight="0.49626866" weight="0.33804348" />
<window_info anchor="bottom" id="Database Changes" order="9" sideWeight="0.49946696" weight="0.32826087" />
<window_info anchor="bottom" id="Event Log" order="10" sideWeight="0.48027718" side_tool="true" visible="true" weight="0.32717392" />
<window_info anchor="bottom" id="Version Control" order="11" sideWeight="0.4978678" weight="0.15326087" />
<window_info anchor="bottom" id="Terminal" order="12" sideWeight="0.49520257" weight="0.3576087" />
<window_info anchor="bottom" id="Python Console" order="13" sideWeight="0.4946695" weight="0.1521739" />
<window_info anchor="bottom" id="Database Console" order="14" sideWeight="0.49838188" weight="0.21908894" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="SciView" order="3" weight="0.32995737" />
<window_info anchor="right" id="Database" order="4" visible="true" weight="0.20469083" />
<window_info anchor="right" id="Database" order="4" visible="true" weight="0.102345414" />
</layout>
<layout-to-restore>
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.15138593" />
@ -695,51 +700,6 @@
<option name="myLimit" value="2678400000" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/controls/modal.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-442">
<folding>
<element signature="e#0#50#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManager/urls.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/utils/extended_interpolation_with_env.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="459">
<caret line="92" lean-forward="true" selection-start-line="92" selection-end-line="92" />
</state>
</provider>
</entry>
<entry file="file://C:/Python36/Lib/collections/__init__.py" />
<entry file="file://$USER_HOME$/.PyCharm2018.2/system/python_stubs/-1184660488/builtins.py" />
<entry file="file://$PROJECT_DIR$/YtManagerApp/urls.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="408">
<caret line="33" selection-start-line="33" selection-end-line="33" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/appconfig.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="413">
<caret line="106" lean-forward="true" selection-start-line="106" selection-end-line="106" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/auth.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="11" selection-start-line="11" selection-end-line="11" />
</state>
</provider>
</entry>
<entry file="file://C:/Python36/Lib/configparser.py" />
<entry file="file://C:/Python36/Lib/site-packages/apscheduler/executors/base.py" />
<entry file="file://C:/Python36/Lib/site-packages/django/db/models/fields/related_descriptors.py" />
@ -866,8 +826,6 @@
<caret line="280" column="32" selection-start-line="280" selection-start-column="22" selection-end-line="280" selection-end-column="32" />
<folding>
<element signature="e#0#14#0" expanded="true" />
<marker date="1540831325280" expanded="true" signature="7713:7719" ph="..." />
<marker date="1540831325280" expanded="true" signature="13276:13861" ph="..." />
</folding>
</state>
</provider>
@ -878,8 +836,6 @@
<caret line="8" column="27" selection-start-line="8" selection-start-column="27" selection-end-line="8" selection-end-column="27" />
<folding>
<element signature="e#0#32#0" expanded="true" />
<marker date="1540827548686" expanded="true" signature="184:185" ph="..." />
<marker date="1540827548686" expanded="true" signature="761:766" ph="..." />
</folding>
</state>
</provider>
@ -1009,16 +965,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="41" selection-start-line="41" selection-end-line="41" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/readme.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
@ -1029,5 +975,81 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="41" selection-start-line="41" selection-end-line="41" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/YtManagerApp/models.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="4" selection-start-line="4" selection-end-line="4" />
</state>
</provider>
</entry>
<entry file="file:///usr/lib/python3.6/importlib/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="125" selection-start-line="125" selection-end-line="125" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.PyCharm2018.2/system/python_stubs/-1247971763/builtins.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="197">
<caret line="1312" column="8" selection-start-line="1312" selection-start-column="8" selection-end-line="1312" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="524">
<caret line="84" column="2" selection-start-line="84" selection-start-column="2" selection-end-line="84" selection-end-column="2" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/config/config.ini">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" column="20" selection-start-line="13" selection-end-line="13" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file:///usr/local/lib/python3.6/dist-packages/dj_config_url.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2305">
<caret line="157" column="4" selection-start-line="157" selection-start-column="4" selection-end-line="157" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/YtManager/settings.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="358">
<caret line="207" selection-start-line="207" selection-end-line="207" />
<folding>
<element signature="e#314#323#0" expanded="true" />
<marker date="1541026657396" expanded="true" signature="4447:6293" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/YtManagerApp/appconfig.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="418">
<caret line="107" lean-forward="true" selection-start-line="107" selection-end-line="107" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@ -4,8 +4,8 @@
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="YtManager/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="settingsModule" value="app/YtManager/settings.py" />
<option name="manageScript" value="app/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
@ -13,7 +13,9 @@
</facet>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="jquery-3.3.1" level="application" />
@ -26,11 +28,6 @@
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/YtManagerApp/templates" />
</list>
</option>
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />

View File

@ -26,6 +26,7 @@ Of course, there are a lot of things that still need to be done. The web interfa
* pip: `$ apt install python3-pip`
* django: `$ pip3 install django`
* crispy_forms: `$ pip3 install django-crispy-forms`
* dj-config-url: `$ pip3 install dj-config-url`
* youtube-dl: `$ pip3 install youtube-dl`
* google-api-python-client: `$ pip3 install google-api-python-client`
* google_auth_oauthlib: `$ pip3 install google_auth_oauthlib`
@ -40,14 +41,14 @@ Of course, there are a lot of things that still need to be done. The web interfa
```bash
sudo apt install python3 python3-pip
sudo pip3 install apscheduler django django-crispy-forms youtube-dl google-api-python-client google_auth_oauthlib oauth2client
sudo pip3 install apscheduler django django-crispy-forms dj-config-url youtube-dl google-api-python-client google_auth_oauthlib oauth2client
```
2. Clone this repository:
```bash
git clone https://github.com/chibicitiberiu/ytsm.git
cd ytsm
cd ytsm/app
```
3. Set up the database: `python3 manage.py migrate`
@ -55,16 +56,13 @@ Of course, there are a lot of things that still need to be done. The web interfa
By default, a SQLite database is used, which is located in the project's folder.
You can customize that in `YtManager/settings.py`, by modifying the `DATABASES` variable (search Django documentation for details).
4. Set up the `MEDIA_ROOT` variable in `YtManager/settings.py`. This is where the thumbnails will be downloaded.
(note: this will be moved to `config.ini` in the future).
5. Obtain an YouTube API developer key from [https://console.developers.google.com/apis/dashboard](https://console.developers.google.com/apis/dashboard).
4. Obtain an YouTube API developer key from [https://console.developers.google.com/apis/dashboard](https://console.developers.google.com/apis/dashboard).
You can find a detailed guide on [this page](https://www.slickremix.com/docs/get-api-key-for-youtube/).
The `defaults.ini` file already has an API key, but if the quotas are reached, you won't be able to use this program
any more. Also, I might decide to delete that key, which will break your installation.
6. Modify `config/config.ini` to your liking. All the settings should be documented through comments.
5. Modify `config/config.ini` to your liking. All the settings should be documented through comments.
All these settings apply server-wide. The settings in the `user` section can be overriden from the web page for each
individual user.
@ -73,18 +71,18 @@ individual user.
* `[Global] YoutubeApiKey` - put your YouTube API key here
* `[User] DownloadPath` - sets the folder where videos will be downloaded
7. Start the server: `python3 manage.py runserver [port] --noreload`
6. Start the server: `python3 manage.py runserver [port] --noreload`
The `port` parameter is optional.
The `--noreload` option is necessary, otherwise the scheduler will run on 2 separate processes at the same time,
which is not ideal.
8. Open the server's page in your browser, by entering `http://localhost:port` in your address bar.
7. Open the server's page in your browser, by entering `http://localhost:port` in your address bar.
9. Create an admin user by going to the *register* page, and creating an user account.
8. Create an admin user by going to the *register* page, and creating an user account.
10. Add some subscriptions, and enjoy!
9. Add some subscriptions, and enjoy!
### Docker

View File

@ -11,23 +11,12 @@ https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
import logging
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '^zv8@i2h!ko2lo=%ivq(9e#x=%q*i^^)6#4@(juzdx%&0c+9a0'
YOUTUBE_API_KEY = os.getenv('YTSM_YOUTUBE_API_KEY', 'AIzaSyBabzE4Bup77WexdLMa9rN9z-wJidEfNX8')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
#
# Basic Django stuff
#
ALLOWED_HOSTS = ['*']
SESSION_COOKIE_AGE = 3600 * 30 # one month
# Application definition
@ -76,24 +65,6 @@ TEMPLATES = [
WSGI_APPLICATION = 'YtManager.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': os.getenv('YTSM_DATABASE_ENGINE', 'django.db.backends.sqlite3'),
'NAME': os.getenv('YTSM_DATABASE_NAME', os.path.join(BASE_DIR, 'ytmanager.db')),
'HOST': os.getenv('YTSM_DATABASE_HOST', None),
'USER': os.getenv('YTSM_DATABASE_USERNAME', None),
'PASSWORD': os.getenv('YTSM_DATABASE_PASSWORD', None),
'PORT': os.getenv('YTSM_DATABASE_PORT', None)
}
}
if os.getenv('YTSM_DATABASE_URL', None):
import dj_database_url
DATABASES['default'] = dj_database_url.parse(os.environ['YTSM_DATABASE_URL'], conn_max_age=600)
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
@ -112,6 +83,9 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login'
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
@ -126,14 +100,115 @@ USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = 'data/media'
# Misc Django stuff
CRISPY_TEMPLATE_PACK = 'bootstrap4'
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login'
LOG_FORMAT = '%(asctime)s|%(process)d|%(thread)d|%(name)s|%(filename)s|%(lineno)d|%(levelname)s|%(message)s'
#
# Directories
#
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_DEFAULT_CONFIG_FILE = os.path.join(BASE_DIR, 'config/config.ini')
_DEFAULT_LOG_FILE = os.path.join(BASE_DIR, 'data/log.log')
_DEFAULT_MEDIA_ROOT = os.path.join(BASE_DIR, 'data/media')
DEFAULTS_FILE = os.path.join(BASE_DIR, 'config/defaults.ini')
CONFIG_FILE = os.getenv('YTSM_CONFIG_FILE', _DEFAULT_CONFIG_FILE)
#
# Defaults
#
_DEFAULT_DEBUG = False
_DEFAULT_SECRET_KEY = '^zv8@i2h!ko2lo=%ivq(9e#x=%q*i^^)6#4@(juzdx%&0c+9a0'
_DEFAULT_YOUTUBE_API_KEY = 'AIzaSyBabzE4Bup77WexdLMa9rN9z-wJidEfNX8'
_DEFAULT_DATABASE = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'ytmanager.db'),
'HOST': None,
'USER': None,
'PASSWORD': None,
'PORT': None,
}
_SCHEDULER_SYNC_SCHEDULE = '5 * * * *'
_DEFAULT_SCHEDULER_CONCURRENCY = 1
#
# Load globals from config.ini
#
def load_config_ini():
from configparser import ConfigParser
from YtManagerApp.utils.extended_interpolation_with_env import ExtendedInterpolatorWithEnv
import dj_database_url
cfg = ConfigParser(allow_no_value=True, interpolation=ExtendedInterpolatorWithEnv())
cfg.read([DEFAULTS_FILE, CONFIG_FILE])
# Debug
global DEBUG
DEBUG = cfg.getboolean('global', 'Debug', fallback=_DEFAULT_DEBUG)
# Media root, which is where thumbnails are stored
global MEDIA_ROOT
MEDIA_ROOT = cfg.get('global', 'MediaRoot', fallback=_DEFAULT_MEDIA_ROOT)
# Keys - secret key, youtube API key
# SECURITY WARNING: keep the secret key used in production secret!
global SECRET_KEY, YOUTUBE_API_KEY
SECRET_KEY = cfg.get('global', 'SecretKey', fallback=_DEFAULT_SECRET_KEY)
YOUTUBE_API_KEY = cfg.get('global', 'YoutubeApiKey', fallback=_DEFAULT_YOUTUBE_API_KEY)
# Database
global DATABASES
DATABASES = {
'default': _DEFAULT_DATABASE
}
if cfg.has_option('global', 'DatabaseURL'):
DATABASES['default'] = dj_database_url.parse(cfg.get('global', 'DatabaseURL'))
else:
DATABASES['default'] = {
'ENGINE': cfg.get('global', 'DatabaseEngine', fallback=_DEFAULT_DATABASE['ENGINE']),
'NAME': cfg.get('global', 'DatabaseName', fallback=_DEFAULT_DATABASE['NAME']),
'HOST': cfg.get('global', 'DatabaseHost', fallback=_DEFAULT_DATABASE['HOST']),
'USER': cfg.get('global', 'DatabaseUser', fallback=_DEFAULT_DATABASE['USER']),
'PASSWORD': cfg.get('global', 'DatabasePassword', fallback=_DEFAULT_DATABASE['PASSWORD']),
'PORT': cfg.get('global', 'DatabasePort', fallback=_DEFAULT_DATABASE['PORT']),
}
# Log settings
global LOG_LEVEL, LOG_FILE
log_level_str = cfg.get('global', 'LogLevel', fallback='INFO')
try:
LOG_LEVEL = getattr(logging, log_level_str)
except AttributeError:
print("Invalid log level " + LOG_LEVEL)
LOG_LEVEL = logging.INFO
LOG_FILE = cfg.get('global', 'LogFile', fallback=_DEFAULT_LOG_FILE)
# Scheduler settings
global SCHEDULER_SYNC_SCHEDULE, SCHEDULER_CONCURRENCY
SCHEDULER_SYNC_SCHEDULE = cfg.get('global', 'SynchronizationSchedule', fallback=_SCHEDULER_SYNC_SCHEDULE)
SCHEDULER_CONCURRENCY = cfg.getint('global', 'SchedulerConcurrency', fallback=_DEFAULT_SCHEDULER_CONCURRENCY)
load_config_ini()

View File

@ -12,35 +12,26 @@ from django.contrib.auth.models import User
from .models import UserSettings, Subscription
from .utils.extended_interpolation_with_env import ExtendedInterpolatorWithEnv
_CONFIG_DIR = os.path.join(dj_settings.BASE_DIR, 'config')
_LOG_FILE = 'log.log'
_LOG_PATH = os.path.join(_CONFIG_DIR, _LOG_FILE)
_LOG_FORMAT = '%(asctime)s|%(process)d|%(thread)d|%(name)s|%(filename)s|%(lineno)d|%(levelname)s|%(message)s'
class AppSettings(ConfigParser):
_DEFAULT_INTERPOLATION = ExtendedInterpolatorWithEnv()
__DEFAULTS_FILE = 'defaults.ini'
__SETTINGS_FILE = 'config.ini'
def __init__(self, *args, **kwargs):
super().__init__(allow_no_value=True, *args, **kwargs)
self.__defaults_path = os.path.join(_CONFIG_DIR, AppSettings.__DEFAULTS_FILE)
self.__settings_path = os.path.join(_CONFIG_DIR, AppSettings.__SETTINGS_FILE)
def initialize(self):
self.read([self.__defaults_path, self.__settings_path])
self.read([dj_settings.DEFAULTS_FILE, dj_settings.CONFIG_FILE])
def save(self):
if os.path.exists(self.__settings_path):
if os.path.exists(dj_settings.CONFIG_FILE):
# Create a backup
copyfile(self.__settings_path, self.__settings_path + ".backup")
copyfile(dj_settings.CONFIG_FILE, dj_settings.CONFIG_FILE + ".backup")
else:
# Ensure directory exists
settings_dir = os.path.dirname(self.__settings_path)
settings_dir = os.path.dirname(dj_settings.CONFIG_FILE)
os.makedirs(settings_dir, exist_ok=True)
with open(self.__settings_path, 'w') as f:
with open(dj_settings.CONFIG_FILE, 'w') as f:
self.write(f)
def __get_combined_dict(self, vars: Optional[Any], sub: Optional[Subscription], user: Optional[User]) -> ChainMap:
@ -112,12 +103,10 @@ def initialize_app_config():
def __initialize_logger():
log_level_str = settings.get('global', 'LogLevel', fallback='INFO')
log_dir = os.path.dirname(dj_settings.LOG_FILE)
os.makedirs(log_dir, exist_ok=True)
try:
log_level = getattr(logging, log_level_str)
logging.basicConfig(filename=_LOG_PATH, level=log_level, format=_LOG_FORMAT)
except AttributeError:
logging.basicConfig(filename=_LOG_PATH, level=logging.INFO, format=_LOG_FORMAT)
logging.warning('Invalid log level "%s" in config file.', log_level_str)
logging.basicConfig(
filename=dj_settings.LOG_FILE,
level=dj_settings.LOG_LEVEL,
format=dj_settings.LOG_FORMAT)