From a56da94d1fe8bae240d920b58e2bcd485dc160ca Mon Sep 17 00:00:00 2001 From: Yash Karandikar Date: Sun, 20 Sep 2020 14:36:21 -0500 Subject: [PATCH 01/63] Wrap footer text on smaller screens --- notes/static/notes/dark.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notes/static/notes/dark.css b/notes/static/notes/dark.css index 2410e08..8c93c95 100644 --- a/notes/static/notes/dark.css +++ b/notes/static/notes/dark.css @@ -127,7 +127,8 @@ a.article-title:hover { left: 0; bottom: 0; width: 100%; - height: 18px; + height: auto; + min-height: 18px; background: #1c1c1c; color: white; text-align: center; From 849239be7f32cf37c75367ad905308d395c14476 Mon Sep 17 00:00:00 2001 From: Yash Karandikar Date: Mon, 21 Sep 2020 12:40:40 -0500 Subject: [PATCH 02/63] Remove redundant license badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2b2a469..51ffcc8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@

DomeCode DomeCode

Discord Server - From 4b0674aa6b034a2704bf041c806965400b3578ee Mon Sep 17 00:00:00 2001 From: Arth Tyagi Date: Wed, 23 Sep 2020 00:53:22 +0530 Subject: [PATCH 03/63] Create codeql-analysis.yml --- .github/workflows/codeql-analysis.yml | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..2401b81 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,66 @@ +name: "CodeQL" + +on: + push: + branches: [master] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 22 * * 6' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['python', 'javascript', 'java', 'cpp', 'go'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 From aa679242c043fa4821ed7f027aaa76bea13cdbff Mon Sep 17 00:00:00 2001 From: Arth Tyagi Date: Wed, 23 Sep 2020 00:55:07 +0530 Subject: [PATCH 04/63] Create label.yml --- .github/workflows/label.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/label.yml diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 0000000..7c724a6 --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,19 @@ +# This workflow will triage pull requests and apply a label based on the +# paths that are modified in the pull request. +# +# To use this workflow, you will need to set up a .github/labeler.yml +# file with configuration. For more information, see: +# https://github.com/actions/labeler + +name: Labeler +on: [pull_request] + +jobs: + label: + + runs-on: ubuntu-latest + + steps: + - uses: actions/labeler@v2 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" From cdcce724bf8a3a64d63236b4b70ef8bdb97e78d2 Mon Sep 17 00:00:00 2001 From: Arth Tyagi Date: Wed, 23 Sep 2020 00:55:51 +0530 Subject: [PATCH 05/63] Create greetings.yml --- .github/workflows/greetings.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/greetings.yml diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml new file mode 100644 index 0000000..28ee6b2 --- /dev/null +++ b/.github/workflows/greetings.yml @@ -0,0 +1,13 @@ +name: Greetings + +on: [pull_request, issues] + +jobs: + greeting: + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-message: 'Message that will be displayed on users'' first issue' + pr-message: 'Message that will be displayed on users'' first pr' From 578fa491aba640bd4b8774c8057635c617dcac9c Mon Sep 17 00:00:00 2001 From: Yash Karandikar Date: Tue, 22 Sep 2020 14:28:31 -0500 Subject: [PATCH 06/63] Automatically run black code formatter for python code --- .github/workflows/autoblack.yml | 24 ++++++++++++++++++++++++ .github/workflows/pythonlint.yml | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .github/workflows/autoblack.yml create mode 100644 .github/workflows/pythonlint.yml diff --git a/.github/workflows/autoblack.yml b/.github/workflows/autoblack.yml new file mode 100644 index 0000000..44249f7 --- /dev/null +++ b/.github/workflows/autoblack.yml @@ -0,0 +1,24 @@ +# GitHub Action that uses Black to reformat Python code (if needed) when doing a git push. +# If all Python code in the repo is compliant with Black then this Action does nothing. +# Otherwise, Black is run and its changes are committed to the repo. +# https://github.com/cclauss/autoblack + +name: autoblack_push +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 # Use v1, NOT v2 + - uses: actions/setup-python@v2 + - run: pip install black + - run: black --check . + - name: If needed, commit black changes to a new pull request + if: failure() + run: | + black . + git config --global user.name github-actions + git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY + git commit -am "fixup! Format Python code with psf/black push" + git push --force origin HEAD:$GITHUB_REF diff --git a/.github/workflows/pythonlint.yml b/.github/workflows/pythonlint.yml new file mode 100644 index 0000000..71f6764 --- /dev/null +++ b/.github/workflows/pythonlint.yml @@ -0,0 +1,24 @@ +name: PythonLint +on: [pull_request] + +jobs: + Flask8Test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics From 99b91f5d8a2143831f55d5d498ad8abdf6206db7 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 22 Sep 2020 19:29:41 +0000 Subject: [PATCH 07/63] fixup! Format Python code with psf/black push --- coder/apps.py | 5 +- coder/compare.py | 2 - coder/forms.py | 7 +- coder/migrations/0001_initial.py | 84 +++++- coder/migrations/0002_answer_user.py | 13 +- coder/migrations/0003_auto_20200725_1936.py | 13 +- .../0004_remove_question_iscorrect.py | 6 +- coder/migrations/0005_question_iscorrect.py | 6 +- .../0006_remove_question_iscorrect.py | 6 +- coder/migrations/0007_question_typeof.py | 17 +- coder/migrations/0008_auto_20200726_2254.py | 34 ++- coder/migrations/0009_auto_20200805_2110.py | 6 +- coder/migrations/0010_auto_20200822_0252.py | 23 +- coder/migrations/0011_auto_20200822_1942.py | 21 +- coder/migrations/0012_auto_20200822_2009.py | 17 +- coder/migrations/0013_answer_language.py | 18 +- coder/migrations/0014_auto_20200823_0155.py | 17 +- coder/migrations/0015_auto_20200823_0317.py | 17 +- coder/migrations/0016_auto_20200823_1210.py | 18 +- coder/migrations/0017_auto_20200823_1311.py | 61 +++- coder/models.py | 77 +++--- coder/templatetags/viewans.py | 3 +- coder/tests.py | 102 +++---- coder/urls.py | 28 +- coder/views.py | 154 ++++++----- creator/apps.py | 2 +- creator/migrations/0001_initial.py | 54 ++-- creator/migrations/0002_auto_20200813_1239.py | 6 +- creator/migrations/0003_auto_20200817_1334.py | 14 +- creator/migrations/0004_auto_20200817_1338.py | 14 +- .../0005_product_additional_file.py | 25 +- creator/migrations/0006_auto_20200817_1417.py | 8 +- creator/migrations/0007_auto_20200817_1452.py | 14 +- creator/models.py | 20 +- creator/templatetags/countproducts.py | 3 +- creator/tests.py | 161 ++++++----- creator/urls.py | 25 +- creator/views.py | 55 ++-- devmanage.py | 4 +- domecode/asgi.py | 2 +- domecode/devsettings.py | 238 ++++++++-------- domecode/settings.py | 260 ++++++++---------- domecode/urls.py | 51 ++-- domecode/wsgi.py | 2 +- forum/admin.py | 1 + forum/apps.py | 2 +- forum/migrations/0001_initial.py | 85 ++++-- forum/migrations/0002_query_slug.py | 6 +- forum/migrations/0003_answer_slug.py | 6 +- forum/migrations/0004_auto_20200725_0400.py | 17 +- forum/migrations/0005_auto_20200725_0401.py | 17 +- forum/migrations/0006_auto_20200725_0406.py | 17 +- forum/migrations/0007_answer_isaccepted.py | 6 +- forum/migrations/0008_comment.py | 38 ++- forum/migrations/0009_auto_20200803_0125.py | 6 +- forum/migrations/0010_auto_20200805_2110.py | 14 +- forum/models.py | 33 ++- forum/templatetags/forumtags.py | 7 +- forum/urls.py | 117 +++++--- forum/views.py | 111 ++++---- fusion/apps.py | 2 +- fusion/urls.py | 11 +- fusion/views.py | 4 +- manage.py | 4 +- notes/admin.py | 3 +- notes/api/serializers.py | 6 +- notes/api/urls.py | 8 +- notes/api/views.py | 19 +- notes/apps.py | 2 +- notes/migrations/0001_initial.py | 32 ++- notes/migrations/0002_auto_20200805_2110.py | 6 +- notes/models.py | 2 +- notes/templatetags/countit.py | 3 +- notes/tests.py | 141 ++++++---- notes/urls.py | 36 ++- notes/views.py | 61 ++-- quizzes/apps.py | 2 +- quizzes/forms.py | 2 +- quizzes/migrations/0001_initial.py | 119 ++++++-- quizzes/migrations/0002_quiz_slug.py | 6 +- quizzes/migrations/0003_ques_language.py | 18 +- quizzes/migrations/0004_auto_20200801_0749.py | 19 +- quizzes/migrations/0005_auto_20200802_1650.py | 18 +- quizzes/migrations/0006_auto_20200802_1652.py | 18 +- quizzes/migrations/0007_auto_20200805_2110.py | 10 +- quizzes/models.py | 58 ++-- quizzes/tests.py | 184 +++++++++---- quizzes/urls.py | 11 +- quizzes/views.py | 25 +- resources/apps.py | 2 +- resources/migrations/0001_initial.py | 40 ++- .../migrations/0002_resource_serialno.py | 6 +- .../migrations/0003_auto_20200727_0345.py | 6 +- .../migrations/0004_auto_20200727_2300.py | 6 +- .../migrations/0005_auto_20200805_2110.py | 6 +- resources/migrations/0006_resource_isdone.py | 6 +- .../migrations/0007_remove_resource_isdone.py | 6 +- resources/migrations/0008_resource_isdone.py | 6 +- .../migrations/0009_auto_20200809_2224.py | 37 ++- resources/migrations/0010_progress_slug.py | 6 +- resources/models.py | 18 +- resources/urls.py | 11 +- resources/views.py | 17 +- todo/admin.py | 2 +- todo/api/serializers.py | 6 +- todo/api/urls.py | 8 +- todo/api/views.py | 9 +- todo/apps.py | 2 +- todo/migrations/0001_initial.py | 26 +- todo/models.py | 17 +- todo/templatetags/countodo.py | 3 +- todo/tests/test_models.py | 23 +- todo/tests/test_urls.py | 50 ++-- todo/tests/test_views.py | 2 +- todo/urls.py | 11 +- todo/views.py | 29 +- users/admin.py | 3 +- users/apps.py | 2 +- users/forms.py | 12 +- users/migrations/0001_initial.py | 33 ++- users/migrations/0002_profile_about.py | 6 +- users/migrations/0003_auto_20200724_2225.py | 13 +- users/migrations/0004_auto_20200724_2226.py | 14 +- users/migrations/0005_profile_points.py | 6 +- .../migrations/0006_profile_githubusername.py | 6 +- users/migrations/0007_auto_20200731_0018.py | 8 +- users/migrations/0008_auto_20200731_0021.py | 8 +- users/migrations/0009_auto_20200803_0249.py | 8 +- users/migrations/0010_auto_20200805_2110.py | 6 +- users/migrations/0011_auto_20200810_1515.py | 6 +- users/models.py | 28 +- users/signals.py | 1 + users/urls.py | 12 +- users/views.py | 26 +- 134 files changed, 2197 insertions(+), 1388 deletions(-) diff --git a/coder/apps.py b/coder/apps.py index c45c5f3..542b7b5 100644 --- a/coder/apps.py +++ b/coder/apps.py @@ -2,7 +2,4 @@ class CoderConfig(AppConfig): - name = 'coder' - - - + name = "coder" diff --git a/coder/compare.py b/coder/compare.py index a3004d4..bbca8a4 100644 --- a/coder/compare.py +++ b/coder/compare.py @@ -1,5 +1,3 @@ - - """ def compare(solution, result): is_same = True diff --git a/coder/forms.py b/coder/forms.py index 000666b..09631bc 100644 --- a/coder/forms.py +++ b/coder/forms.py @@ -5,8 +5,9 @@ class ResultForm(forms.ModelForm): result = forms.FileField( - validators=[FileExtensionValidator(allowed_extensions=['txt'])]) - + validators=[FileExtensionValidator(allowed_extensions=["txt"])] + ) + class Meta: model = Answer - fields = ['result'] + fields = ["result"] diff --git a/coder/migrations/0001_initial.py b/coder/migrations/0001_initial.py index 73d15f2..84a4ae9 100644 --- a/coder/migrations/0001_initial.py +++ b/coder/migrations/0001_initial.py @@ -10,29 +10,83 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Question', + name="Question", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('content', ckeditor.fields.RichTextField()), - ('iscorrect', models.BooleanField(default=False)), - ('category', models.CharField(choices=[('EASY', 'Easy Difficulty'), ('MEDIUM', 'Medium Difficulty'), ('HARD', 'Hard Difficulty'), ('ADVANCED', 'Advanced Difficulty')], default='MEDIUM', max_length=10)), - ('solution', models.FileField(upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt'])])), - ('slug', models.SlugField(null=True, unique=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=100)), + ("content", ckeditor.fields.RichTextField()), + ("iscorrect", models.BooleanField(default=False)), + ( + "category", + models.CharField( + choices=[ + ("EASY", "Easy Difficulty"), + ("MEDIUM", "Medium Difficulty"), + ("HARD", "Hard Difficulty"), + ("ADVANCED", "Advanced Difficulty"), + ], + default="MEDIUM", + max_length=10, + ), + ), + ( + "solution", + models.FileField( + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=["txt"] + ) + ], + ), + ), + ("slug", models.SlugField(null=True, unique=True)), ], ), migrations.CreateModel( - name='Answer', + name="Answer", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('iscorrect', models.BooleanField(default=False)), - ('result', models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt'])])), - ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='coder.Question')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("iscorrect", models.BooleanField(default=False)), + ( + "result", + models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=["txt"] + ) + ], + ), + ), + ( + "question", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="coder.Question" + ), + ), ], ), ] diff --git a/coder/migrations/0002_answer_user.py b/coder/migrations/0002_answer_user.py index 44c165d..290429e 100644 --- a/coder/migrations/0002_answer_user.py +++ b/coder/migrations/0002_answer_user.py @@ -9,13 +9,18 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('coder', '0001_initial'), + ("coder", "0001_initial"), ] operations = [ migrations.AddField( - model_name='answer', - name='user', - field=models.ForeignKey(default='1', on_delete=django.db.models.deletion.CASCADE, related_name='useranswer', to=settings.AUTH_USER_MODEL), + model_name="answer", + name="user", + field=models.ForeignKey( + default="1", + on_delete=django.db.models.deletion.CASCADE, + related_name="useranswer", + to=settings.AUTH_USER_MODEL, + ), ), ] diff --git a/coder/migrations/0003_auto_20200725_1936.py b/coder/migrations/0003_auto_20200725_1936.py index aaba7fa..db596bf 100644 --- a/coder/migrations/0003_auto_20200725_1936.py +++ b/coder/migrations/0003_auto_20200725_1936.py @@ -9,13 +9,18 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('coder', '0002_answer_user'), + ("coder", "0002_answer_user"), ] operations = [ migrations.AlterField( - model_name='answer', - name='user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='submissionuser', to=settings.AUTH_USER_MODEL), + model_name="answer", + name="user", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="submissionuser", + to=settings.AUTH_USER_MODEL, + ), ), ] diff --git a/coder/migrations/0004_remove_question_iscorrect.py b/coder/migrations/0004_remove_question_iscorrect.py index 8b9af2e..af343bf 100644 --- a/coder/migrations/0004_remove_question_iscorrect.py +++ b/coder/migrations/0004_remove_question_iscorrect.py @@ -6,12 +6,12 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0003_auto_20200725_1936'), + ("coder", "0003_auto_20200725_1936"), ] operations = [ migrations.RemoveField( - model_name='question', - name='iscorrect', + model_name="question", + name="iscorrect", ), ] diff --git a/coder/migrations/0005_question_iscorrect.py b/coder/migrations/0005_question_iscorrect.py index 132824d..c637185 100644 --- a/coder/migrations/0005_question_iscorrect.py +++ b/coder/migrations/0005_question_iscorrect.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0004_remove_question_iscorrect'), + ("coder", "0004_remove_question_iscorrect"), ] operations = [ migrations.AddField( - model_name='question', - name='iscorrect', + model_name="question", + name="iscorrect", field=models.BooleanField(default=False), ), ] diff --git a/coder/migrations/0006_remove_question_iscorrect.py b/coder/migrations/0006_remove_question_iscorrect.py index 4f8ae5f..3b22ec9 100644 --- a/coder/migrations/0006_remove_question_iscorrect.py +++ b/coder/migrations/0006_remove_question_iscorrect.py @@ -6,12 +6,12 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0005_question_iscorrect'), + ("coder", "0005_question_iscorrect"), ] operations = [ migrations.RemoveField( - model_name='question', - name='iscorrect', + model_name="question", + name="iscorrect", ), ] diff --git a/coder/migrations/0007_question_typeof.py b/coder/migrations/0007_question_typeof.py index 7111161..bf9504d 100644 --- a/coder/migrations/0007_question_typeof.py +++ b/coder/migrations/0007_question_typeof.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0006_remove_question_iscorrect'), + ("coder", "0006_remove_question_iscorrect"), ] operations = [ migrations.AddField( - model_name='question', - name='typeof', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++')], default='PYTHON', max_length=10), + model_name="question", + name="typeof", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0008_auto_20200726_2254.py b/coder/migrations/0008_auto_20200726_2254.py index f32bc28..8351809 100644 --- a/coder/migrations/0008_auto_20200726_2254.py +++ b/coder/migrations/0008_auto_20200726_2254.py @@ -6,18 +6,38 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0007_question_typeof'), + ("coder", "0007_question_typeof"), ] operations = [ migrations.AlterField( - model_name='question', - name='category', - field=models.CharField(choices=[('EASY', 'Easy Difficulty'), ('MEDIUM', 'Medium Difficulty'), ('HARD', 'Hard Difficulty'), ('ADVANCED', 'Advanced Difficulty'), ('IMPLEMENT', 'Implementation')], default='MEDIUM', max_length=10), + model_name="question", + name="category", + field=models.CharField( + choices=[ + ("EASY", "Easy Difficulty"), + ("MEDIUM", "Medium Difficulty"), + ("HARD", "Hard Difficulty"), + ("ADVANCED", "Advanced Difficulty"), + ("IMPLEMENT", "Implementation"), + ], + default="MEDIUM", + max_length=10, + ), ), migrations.AlterField( - model_name='question', - name='typeof', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=10), + model_name="question", + name="typeof", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0009_auto_20200805_2110.py b/coder/migrations/0009_auto_20200805_2110.py index c2972a7..da63add 100644 --- a/coder/migrations/0009_auto_20200805_2110.py +++ b/coder/migrations/0009_auto_20200805_2110.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0008_auto_20200726_2254'), + ("coder", "0008_auto_20200726_2254"), ] operations = [ migrations.AlterField( - model_name='question', - name='slug', + model_name="question", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/coder/migrations/0010_auto_20200822_0252.py b/coder/migrations/0010_auto_20200822_0252.py index 5dae49b..73e0f78 100644 --- a/coder/migrations/0010_auto_20200822_0252.py +++ b/coder/migrations/0010_auto_20200822_0252.py @@ -7,18 +7,27 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0009_auto_20200805_2110'), + ("coder", "0009_auto_20200805_2110"), ] operations = [ migrations.AddField( - model_name='answer', - name='status', - field=models.CharField(default='In Queue', max_length=100), + model_name="answer", + name="status", + field=models.CharField(default="In Queue", max_length=100), ), migrations.AlterField( - model_name='answer', - name='result', - field=models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt, py, java, cpp, c++'])]), + model_name="answer", + name="result", + field=models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=["txt, py, java, cpp, c++"] + ) + ], + ), ), ] diff --git a/coder/migrations/0011_auto_20200822_1942.py b/coder/migrations/0011_auto_20200822_1942.py index 1bd6811..6620809 100644 --- a/coder/migrations/0011_auto_20200822_1942.py +++ b/coder/migrations/0011_auto_20200822_1942.py @@ -7,18 +7,27 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0010_auto_20200822_0252'), + ("coder", "0010_auto_20200822_0252"), ] operations = [ migrations.AddField( - model_name='answer', - name='response_from_judge', + model_name="answer", + name="response_from_judge", field=models.TextField(null=True), ), migrations.AlterField( - model_name='answer', - name='result', - field=models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt', 'py', 'java', 'cpp', 'c++'])]), + model_name="answer", + name="result", + field=models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=["txt", "py", "java", "cpp", "c++"] + ) + ], + ), ), ] diff --git a/coder/migrations/0012_auto_20200822_2009.py b/coder/migrations/0012_auto_20200822_2009.py index a795988..dea2209 100644 --- a/coder/migrations/0012_auto_20200822_2009.py +++ b/coder/migrations/0012_auto_20200822_2009.py @@ -7,13 +7,22 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0011_auto_20200822_1942'), + ("coder", "0011_auto_20200822_1942"), ] operations = [ migrations.AlterField( - model_name='answer', - name='result', - field=models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt', 'py', 'java', 'cpp', 'c++', 'rs'])]), + model_name="answer", + name="result", + field=models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=["txt", "py", "java", "cpp", "c++", "rs"] + ) + ], + ), ), ] diff --git a/coder/migrations/0013_answer_language.py b/coder/migrations/0013_answer_language.py index e71fe41..cb07aa2 100644 --- a/coder/migrations/0013_answer_language.py +++ b/coder/migrations/0013_answer_language.py @@ -6,13 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0012_auto_20200822_2009'), + ("coder", "0012_auto_20200822_2009"), ] operations = [ migrations.AddField( - model_name='answer', - name='language', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=10), + model_name="answer", + name="language", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0014_auto_20200823_0155.py b/coder/migrations/0014_auto_20200823_0155.py index f0c958d..28d5345 100644 --- a/coder/migrations/0014_auto_20200823_0155.py +++ b/coder/migrations/0014_auto_20200823_0155.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0013_answer_language'), + ("coder", "0013_answer_language"), ] operations = [ migrations.AlterField( - model_name='question', - name='typeof', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++')], default='PYTHON', max_length=10), + model_name="question", + name="typeof", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0015_auto_20200823_0317.py b/coder/migrations/0015_auto_20200823_0317.py index 47c8d74..038846b 100644 --- a/coder/migrations/0015_auto_20200823_0317.py +++ b/coder/migrations/0015_auto_20200823_0317.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0014_auto_20200823_0155'), + ("coder", "0014_auto_20200823_0155"), ] operations = [ migrations.AlterField( - model_name='answer', - name='language', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++')], default='PYTHON', max_length=10), + model_name="answer", + name="language", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0016_auto_20200823_1210.py b/coder/migrations/0016_auto_20200823_1210.py index a64e209..058e9bf 100644 --- a/coder/migrations/0016_auto_20200823_1210.py +++ b/coder/migrations/0016_auto_20200823_1210.py @@ -6,13 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0015_auto_20200823_0317'), + ("coder", "0015_auto_20200823_0317"), ] operations = [ migrations.AlterField( - model_name='question', - name='typeof', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=10), + model_name="question", + name="typeof", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/migrations/0017_auto_20200823_1311.py b/coder/migrations/0017_auto_20200823_1311.py index 76ac556..63d614d 100644 --- a/coder/migrations/0017_auto_20200823_1311.py +++ b/coder/migrations/0017_auto_20200823_1311.py @@ -7,23 +7,64 @@ class Migration(migrations.Migration): dependencies = [ - ('coder', '0016_auto_20200823_1210'), + ("coder", "0016_auto_20200823_1210"), ] operations = [ migrations.AlterField( - model_name='answer', - name='language', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('GO', 'Go'), ('C', 'C')], default='PYTHON', max_length=10), + model_name="answer", + name="language", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("GO", "Go"), + ("C", "C"), + ], + default="PYTHON", + max_length=10, + ), ), migrations.AlterField( - model_name='answer', - name='result', - field=models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['txt', 'py', 'java', 'cpp', 'c++', 'rs', 'go', 'c'])]), + model_name="answer", + name="result", + field=models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=[ + "txt", + "py", + "java", + "cpp", + "c++", + "rs", + "go", + "c", + ] + ) + ], + ), ), migrations.AlterField( - model_name='question', - name='typeof', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('GO', 'Go'), ('C', 'C'), ('General', 'General')], default='PYTHON', max_length=10), + model_name="question", + name="typeof", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("GO", "Go"), + ("C", "C"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/coder/models.py b/coder/models.py index 3504d46..f0202c8 100644 --- a/coder/models.py +++ b/coder/models.py @@ -8,28 +8,29 @@ class Question(models.Model): CATEGORY = [ - ('EASY', 'Easy Difficulty'), - ('MEDIUM', 'Medium Difficulty'), - ('HARD', 'Hard Difficulty'), - ('ADVANCED', 'Advanced Difficulty'), - ('IMPLEMENT', 'Implementation') + ("EASY", "Easy Difficulty"), + ("MEDIUM", "Medium Difficulty"), + ("HARD", "Hard Difficulty"), + ("ADVANCED", "Advanced Difficulty"), + ("IMPLEMENT", "Implementation"), ] TYPE = [ - ('JAVA', 'Java'), - ('PYTHON', 'Python'), - ('RUST', 'Rust'), - ('C++', 'C++'), - ('GO', 'Go'), - ('C', 'C'), - ('General', 'General') + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("GO", "Go"), + ("C", "C"), + ("General", "General"), ] title = models.CharField(max_length=100) content = RichTextField() - category = models.CharField( - max_length=10, choices=CATEGORY, default='MEDIUM') - typeof = models.CharField(max_length=10, choices=TYPE, default='PYTHON') + category = models.CharField(max_length=10, choices=CATEGORY, default="MEDIUM") + typeof = models.CharField(max_length=10, choices=TYPE, default="PYTHON") solution = models.FileField( - validators=[FileExtensionValidator(allowed_extensions=['txt'])], upload_to='media') + validators=[FileExtensionValidator(allowed_extensions=["txt"])], + upload_to="media", + ) slug = models.SlugField(null=True, unique=True, max_length=256) def __str__(self): @@ -40,34 +41,48 @@ def save(self, *args, **kwargs): super().save(*args, **kwargs) def get_absolute_url(self): - return reverse('coder:detail', kwargs={'slug': self.slug}) + return reverse("coder:detail", kwargs={"slug": self.slug}) class Answer(models.Model): TYPE = [ - ('JAVA', 'Java'), - ('PYTHON', 'Python'), - ('RUST', 'Rust'), - ('C++', 'C++'), - ('GO', 'Go'), - ('C', 'C'), + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("GO", "Go"), + ("C", "C"), ] - user = models.ForeignKey(get_user_model( - ), null=True, on_delete=models.SET_NULL, related_name="submissionuser") + user = models.ForeignKey( + get_user_model(), + null=True, + on_delete=models.SET_NULL, + related_name="submissionuser", + ) question = models.ForeignKey(Question, on_delete=models.CASCADE) iscorrect = models.BooleanField(default=False) - language = models.CharField(max_length=10, choices=TYPE, default='PYTHON') # Stores the language ofc + language = models.CharField( + max_length=10, choices=TYPE, default="PYTHON" + ) # Stores the language ofc - status = models.CharField(max_length=100, default='In Queue') # Added the status field + status = models.CharField( + max_length=100, default="In Queue" + ) # Added the status field response_from_judge = models.TextField(null=True) # Stores the response received from judge. Can be helpful in debugging later. result = models.FileField( - validators=[FileExtensionValidator(allowed_extensions=['txt', 'py', 'java', 'cpp', 'c++', 'rs', 'go', 'c'])], - upload_to='media', + validators=[ + FileExtensionValidator( + allowed_extensions=["txt", "py", "java", "cpp", "c++", "rs", "go", "c"] + ) + ], + upload_to="media", blank=True, - null=True) # Allowed for other types of file extensions + null=True, + ) # Allowed for other types of file extensions + # result = models.FileField( null= True, blank=True, default = 'media/media/output.txt', - # validators=[FileExtensionValidator(allowed_extensions=['txt'])], upload_to= 'media') +# validators=[FileExtensionValidator(allowed_extensions=['txt'])], upload_to= 'media') diff --git a/coder/templatetags/viewans.py b/coder/templatetags/viewans.py index a6a352f..7e8ac3c 100644 --- a/coder/templatetags/viewans.py +++ b/coder/templatetags/viewans.py @@ -6,8 +6,7 @@ @register.simple_tag def notsolved(user, question): - if Answer.objects.filter(user=user,question = question, iscorrect=True).count() <1: + if Answer.objects.filter(user=user, question=question, iscorrect=True).count() < 1: return True else: return False - \ No newline at end of file diff --git a/coder/tests.py b/coder/tests.py index 25683b7..18eed14 100644 --- a/coder/tests.py +++ b/coder/tests.py @@ -4,6 +4,7 @@ from django.test import Client from django.urls import reverse from django.core.files.uploadedfile import SimpleUploadedFile + # Create your tests here. @@ -14,10 +15,10 @@ def create_user(username, password): return user -def create_question(language='PYTHON'): - with open('coder/testfiles/output.txt') as file: - f = SimpleUploadedFile('normal.txt', str.encode(file.read())) - question = Question(title='Test', content='Test', solution=f, typeof=language) +def create_question(language="PYTHON"): + with open("coder/testfiles/output.txt") as file: + f = SimpleUploadedFile("normal.txt", str.encode(file.read())) + question = Question(title="Test", content="Test", solution=f, typeof=language) question.save() return question @@ -30,78 +31,84 @@ def test_correct_answer_works_python(self): """ Check if checking works correctly for python program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - ques1 = create_question('PYTHON') - with open('coder/testfiles/normal.py') as f: + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + ques1 = create_question("PYTHON") + with open("coder/testfiles/normal.py") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'PYTHON', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "PYTHON", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_correct_answer_works_java(self): """ Check if checking works correctly for java program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") ques1 = create_question() - with open('coder/testfiles/normal.java') as f: + with open("coder/testfiles/normal.java") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'JAVA', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "JAVA", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_correct_answer_works_cpp(self): """ Check if checking works correctly for c++ program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") ques1 = create_question() - with open('coder/testfiles/normal.cpp') as f: + with open("coder/testfiles/normal.cpp") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'C++', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "C++", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_correct_answer_works_rust(self): """ Check if checking works correctly for rust program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") ques1 = create_question() - with open('coder/testfiles/normal.rs') as f: + with open("coder/testfiles/normal.rs") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'RUST', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "RUST", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_correct_answer_works_go(self): """ Check if checking works correctly for rust program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") ques1 = create_question() - with open('coder/testfiles/normal.go') as f: + with open("coder/testfiles/normal.go") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'GO', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "GO", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_correct_answer_works_c(self): """ Check if checking works correctly for rust program """ - create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') + create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") ques1 = create_question() - with open('coder/testfiles/normal.c') as f: + with open("coder/testfiles/normal.c") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'C', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "C", "result": f}, + ) self.assertTrue(Answer.objects.all()[0].iscorrect) def test_multiple_correct_answers_increase_domes_once(self): @@ -109,23 +116,26 @@ def test_multiple_correct_answers_increase_domes_once(self): Even if the user submits the answer after having solved the question once their points shouldn't increase """ - user = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - ques1 = create_question('PYTHON') - with open('coder/testfiles/normal.java') as f: + user = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + ques1 = create_question("PYTHON") + with open("coder/testfiles/normal.java") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'PYTHON', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "PYTHON", "result": f}, + ) user.refresh_from_db() self.assertEqual(user.profile.domes, 0) - with open('coder/testfiles/normal.py') as f: + with open("coder/testfiles/normal.py") as f: self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'PYTHON', 'result': f}) + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "PYTHON", "result": f}, + ) self.client.post( - reverse("coder:submit", kwargs={'qslug': ques1.slug}), - data={'language': 'PYTHON', 'result': f}) # Post the correct answer twice + reverse("coder:submit", kwargs={"qslug": ques1.slug}), + data={"language": "PYTHON", "result": f}, + ) # Post the correct answer twice user.refresh_from_db() self.assertEqual(user.profile.domes, 15) diff --git a/coder/urls.py b/coder/urls.py index eca2281..dca13a0 100644 --- a/coder/urls.py +++ b/coder/urls.py @@ -1,14 +1,22 @@ from django.urls import path -from .import views -from .views import CoderListViewPy, CoderListViewJava, CoderListViewGen, CoderDetailView, CoderCreateView, SubmissionListView -app_name = 'coder' +from . import views +from .views import ( + CoderListViewPy, + CoderListViewJava, + CoderListViewGen, + CoderDetailView, + CoderCreateView, + SubmissionListView, +) + +app_name = "coder" urlpatterns = [ - path('', views.coderhome, name='home'), - path('python/', CoderListViewPy.as_view(), name='list-python'), - path('java/', CoderListViewJava.as_view(), name='list-java'), - path('general/', CoderListViewGen.as_view(), name='list-general'), - path('question//', CoderDetailView.as_view(), name='detail'), - path('submissions', SubmissionListView.as_view(), name='submissions'), - path('/answer/', CoderCreateView.as_view(), name='submit') + path("", views.coderhome, name="home"), + path("python/", CoderListViewPy.as_view(), name="list-python"), + path("java/", CoderListViewJava.as_view(), name="list-java"), + path("general/", CoderListViewGen.as_view(), name="list-general"), + path("question//", CoderDetailView.as_view(), name="detail"), + path("submissions", SubmissionListView.as_view(), name="submissions"), + path("/answer/", CoderCreateView.as_view(), name="submit"), ] diff --git a/coder/views.py b/coder/views.py index 82a49f4..b99fb72 100644 --- a/coder/views.py +++ b/coder/views.py @@ -2,7 +2,13 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse_lazy, reverse from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin -from django.views.generic import ListView, DetailView, CreateView, UpdateView, RedirectView +from django.views.generic import ( + ListView, + DetailView, + CreateView, + UpdateView, + RedirectView, +) from django.db.models import Q from . import compare from domecode.mixins import PageTitleMixin @@ -15,73 +21,70 @@ def coderhome(request): - return render(request, 'coder/coder_home.html', {'title': 'Practice'}) + return render(request, "coder/coder_home.html", {"title": "Practice"}) class CoderListViewPy(PageTitleMixin, ListView): model = Question template_name = "coder/coder_list_python.html" - context_object_name = 'question' + context_object_name = "question" paginate_by = 15 - title = 'Practice Python' + title = "Practice Python" def get_queryset(self, *args, **kwargs): - object_list = super( - CoderListViewPy, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + object_list = super(CoderListViewPy, self).get_queryset(*args, **kwargs) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__contains=search) | - Q(content__contains=search) | - Q(category__contains=search) + Q(title__contains=search) + | Q(content__contains=search) + | Q(category__contains=search) ) - return object_list.filter(typeof='PYTHON') + return object_list.filter(typeof="PYTHON") else: - return object_list.filter(typeof='PYTHON') + return object_list.filter(typeof="PYTHON") class CoderListViewGen(PageTitleMixin, ListView): model = Question template_name = "coder/coder_list_common.html" - context_object_name = 'question' + context_object_name = "question" paginate_by = 15 - title = 'Practice' + title = "Practice" def get_queryset(self, *args, **kwargs): - object_list = super( - CoderListViewGen, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + object_list = super(CoderListViewGen, self).get_queryset(*args, **kwargs) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__contains=search) | - Q(content__contains=search) | - Q(category__contains=search) + Q(title__contains=search) + | Q(content__contains=search) + | Q(category__contains=search) ) - return object_list.filter(typeof='General') + return object_list.filter(typeof="General") else: - return object_list.filter(typeof='General') + return object_list.filter(typeof="General") class CoderListViewJava(PageTitleMixin, ListView): model = Question template_name = "coder/coder_list_java.html" - context_object_name = 'question' + context_object_name = "question" paginate_by = 15 - title = 'Practice Java' + title = "Practice Java" def get_queryset(self, *args, **kwargs): - object_list = super( - CoderListViewJava, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + object_list = super(CoderListViewJava, self).get_queryset(*args, **kwargs) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__contains=search) | - Q(content__contains=search) | - Q(category__contains=search) + Q(title__contains=search) + | Q(content__contains=search) + | Q(category__contains=search) ) - return object_list.filter(typeof='JAVA') + return object_list.filter(typeof="JAVA") else: - return object_list.filter(typeof='JAVA') + return object_list.filter(typeof="JAVA") class SubmissionListView(PageTitleMixin, LoginRequiredMixin, ListView): @@ -89,7 +92,7 @@ class SubmissionListView(PageTitleMixin, LoginRequiredMixin, ListView): template_name = "coder/submissions.html" context_object_name = "submission" paginate_by = 25 - title = 'Your Submissions' + title = "Your Submissions" def get_queryset(self, *args, **kwargs): object_list = Answer.objects.filter(user=self.request.user) @@ -99,71 +102,94 @@ def get_queryset(self, *args, **kwargs): class CoderDetailView(PageTitleMixin, DetailView): model = Question template_name = "coder/coder_detail.html" - context_object_name = 'question' - title = 'Practice' + context_object_name = "question" + title = "Practice" class CoderCreateView(PageTitleMixin, LoginRequiredMixin, CreateView): model = Answer - fields = ['result', 'language'] - context_object_name = 'answer' + fields = ["result", "language"] + context_object_name = "answer" template_name = "coder/coder_form.html" - title = 'Submit' + title = "Submit" def get_success_url(self): question = self.object.question - return reverse('coder:detail', kwargs={'slug': question.slug}) + return reverse("coder:detail", kwargs={"slug": question.slug}) def form_valid(self, form): form.instance.user = self.request.user - question = Question.objects.get(slug=self.kwargs['qslug']) + question = Question.objects.get(slug=self.kwargs["qslug"]) form.instance.question = question - expected_output = question.solution.read().decode('utf-8') # API won't compile this if you don't decode - src_code = form.instance.result.read().decode('utf-8') + expected_output = question.solution.read().decode( + "utf-8" + ) # API won't compile this if you don't decode + src_code = form.instance.result.read().decode("utf-8") # Judge API - API_URL = 'https://judge0.p.rapidapi.com/submissions/' + API_URL = "https://judge0.p.rapidapi.com/submissions/" querystring = {"base64_encoded": "false"} # Later change to wait = false headers_post = { - 'x-rapidapi-host': "judge0.p.rapidapi.com", - 'x-rapidapi-key': settings.JUDGE0_RAPID_API_KEY, - 'content-type': "application/json", - 'accept': "application/json" - } + "x-rapidapi-host": "judge0.p.rapidapi.com", + "x-rapidapi-key": settings.JUDGE0_RAPID_API_KEY, + "content-type": "application/json", + "accept": "application/json", + } - LANGUAGE_CODES = {'PYTHON': 71, 'JAVA': 62, 'C++': 54, 'RUST': 73, 'GO': 60, 'C': 50} + LANGUAGE_CODES = { + "PYTHON": 71, + "JAVA": 62, + "C++": 54, + "RUST": 73, + "GO": 60, + "C": 50, + } # Update above line whenever a new language is added data_post = { - 'source_code': src_code, - 'language_id': LANGUAGE_CODES[form.instance.language], - 'expected_output': expected_output, + "source_code": src_code, + "language_id": LANGUAGE_CODES[form.instance.language], + "expected_output": expected_output, } data_post = json.dumps(data_post) - response = requests.post(url=API_URL, data=data_post, headers=headers_post, params=querystring) - token = json.loads(response.text)['token'] + response = requests.post( + url=API_URL, data=data_post, headers=headers_post, params=querystring + ) + token = json.loads(response.text)["token"] headers_get = { - 'x-rapidapi-host': "judge0.p.rapidapi.com", - 'x-rapidapi-key': settings.JUDGE0_RAPID_API_KEY} - status = 'Processing' + "x-rapidapi-host": "judge0.p.rapidapi.com", + "x-rapidapi-key": settings.JUDGE0_RAPID_API_KEY, + } + status = "Processing" i = 0 - while status == 'Processing' or status == 'In Queue': - response2 = requests.request("GET", API_URL+token, headers=headers_get, params=querystring) - status = json.loads(response2.text)['status']['description'] + while status == "Processing" or status == "In Queue": + response2 = requests.request( + "GET", API_URL + token, headers=headers_get, params=querystring + ) + status = json.loads(response2.text)["status"]["description"] time.sleep(0.1) - i = i+1 - if i == 200: # Break if it takes more than 20 seconds (probably means api is down) + i = i + 1 + if ( + i == 200 + ): # Break if it takes more than 20 seconds (probably means api is down) status = "TLE" # Setting the status = TLE break form.instance.status = status form.instance.response_from_judge = response2.text - form.instance.iscorrect = (form.instance.status == 'Accepted') - if (form.instance.iscorrect and Answer.objects.filter(question=question).filter(iscorrect=True).filter(user=form.instance.user).count() == 0): + form.instance.iscorrect = form.instance.status == "Accepted" + if ( + form.instance.iscorrect + and Answer.objects.filter(question=question) + .filter(iscorrect=True) + .filter(user=form.instance.user) + .count() + == 0 + ): if form.instance.question.category == "EASY": form.instance.user.profile.domes += 10 if form.instance.question.category == "MEDIUM": diff --git a/creator/apps.py b/creator/apps.py index 500abb7..6c1d268 100644 --- a/creator/apps.py +++ b/creator/apps.py @@ -2,4 +2,4 @@ class CreatorConfig(AppConfig): - name = 'creator' + name = "creator" diff --git a/creator/migrations/0001_initial.py b/creator/migrations/0001_initial.py index 82e6a4c..d07ee1e 100644 --- a/creator/migrations/0001_initial.py +++ b/creator/migrations/0001_initial.py @@ -15,24 +15,44 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Product', + name="Product", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200)), - ('date', models.DateTimeField(auto_now=True)), - ('description', models.TextField()), - ('category', models.CharField(max_length=50)), - ('github_repo', models.CharField(blank=True, max_length=80, null=True)), - ('producthunt', models.CharField(blank=True, max_length=80, null=True)), - ('youtube_videoid', models.CharField(blank=True, max_length=11, null=True)), - ('linkedin', models.CharField(blank=True, max_length=100, null=True)), - ('demo', models.CharField(blank=True, max_length=256, null=True)), - ('contributors', models.TextField()), - ('isreleased', models.BooleanField(default=False)), - ('readmeusers', models.CharField(blank=True, max_length=256, null=True)), - ('readmedevs', models.CharField(blank=True, max_length=256, null=True)), - ('slug', models.SlugField(max_length=256, null=True, unique=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=200)), + ("date", models.DateTimeField(auto_now=True)), + ("description", models.TextField()), + ("category", models.CharField(max_length=50)), + ("github_repo", models.CharField(blank=True, max_length=80, null=True)), + ("producthunt", models.CharField(blank=True, max_length=80, null=True)), + ( + "youtube_videoid", + models.CharField(blank=True, max_length=11, null=True), + ), + ("linkedin", models.CharField(blank=True, max_length=100, null=True)), + ("demo", models.CharField(blank=True, max_length=256, null=True)), + ("contributors", models.TextField()), + ("isreleased", models.BooleanField(default=False)), + ( + "readmeusers", + models.CharField(blank=True, max_length=256, null=True), + ), + ("readmedevs", models.CharField(blank=True, max_length=256, null=True)), + ("slug", models.SlugField(max_length=256, null=True, unique=True)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/creator/migrations/0002_auto_20200813_1239.py b/creator/migrations/0002_auto_20200813_1239.py index 1babcce..3999a70 100644 --- a/creator/migrations/0002_auto_20200813_1239.py +++ b/creator/migrations/0002_auto_20200813_1239.py @@ -7,13 +7,13 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0001_initial'), + ("creator", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='product', - name='description', + model_name="product", + name="description", field=ckeditor.fields.RichTextField(), ), ] diff --git a/creator/migrations/0003_auto_20200817_1334.py b/creator/migrations/0003_auto_20200817_1334.py index fd60e57..cb271cb 100644 --- a/creator/migrations/0003_auto_20200817_1334.py +++ b/creator/migrations/0003_auto_20200817_1334.py @@ -6,18 +6,18 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0002_auto_20200813_1239'), + ("creator", "0002_auto_20200813_1239"), ] operations = [ migrations.RenameField( - model_name='product', - old_name='readmedevs', - new_name='readme_devs', + model_name="product", + old_name="readmedevs", + new_name="readme_devs", ), migrations.RenameField( - model_name='product', - old_name='readmeusers', - new_name='readme_users', + model_name="product", + old_name="readmeusers", + new_name="readme_users", ), ] diff --git a/creator/migrations/0004_auto_20200817_1338.py b/creator/migrations/0004_auto_20200817_1338.py index 7664c95..02d22d4 100644 --- a/creator/migrations/0004_auto_20200817_1338.py +++ b/creator/migrations/0004_auto_20200817_1338.py @@ -6,18 +6,18 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0003_auto_20200817_1334'), + ("creator", "0003_auto_20200817_1334"), ] operations = [ migrations.RenameField( - model_name='product', - old_name='readme_devs', - new_name='documentation_Devs', + model_name="product", + old_name="readme_devs", + new_name="documentation_Devs", ), migrations.RenameField( - model_name='product', - old_name='readme_users', - new_name='documentation_Users', + model_name="product", + old_name="readme_users", + new_name="documentation_Users", ), ] diff --git a/creator/migrations/0005_product_additional_file.py b/creator/migrations/0005_product_additional_file.py index 4373935..b200790 100644 --- a/creator/migrations/0005_product_additional_file.py +++ b/creator/migrations/0005_product_additional_file.py @@ -7,13 +7,30 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0004_auto_20200817_1338'), + ("creator", "0004_auto_20200817_1338"), ] operations = [ migrations.AddField( - model_name='product', - name='additional_File', - field=models.FileField(blank=True, null=True, upload_to='media', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['pdf', 'pptx', 'ppt', 'md', 'txt', 'jpeg', 'png'])]), + model_name="product", + name="additional_File", + field=models.FileField( + blank=True, + null=True, + upload_to="media", + validators=[ + django.core.validators.FileExtensionValidator( + allowed_extensions=[ + "pdf", + "pptx", + "ppt", + "md", + "txt", + "jpeg", + "png", + ] + ) + ], + ), ), ] diff --git a/creator/migrations/0006_auto_20200817_1417.py b/creator/migrations/0006_auto_20200817_1417.py index aa39350..c25e101 100644 --- a/creator/migrations/0006_auto_20200817_1417.py +++ b/creator/migrations/0006_auto_20200817_1417.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0005_product_additional_file'), + ("creator", "0005_product_additional_file"), ] operations = [ migrations.RenameField( - model_name='product', - old_name='github_repo', - new_name='github_Repo_Link', + model_name="product", + old_name="github_repo", + new_name="github_Repo_Link", ), ] diff --git a/creator/migrations/0007_auto_20200817_1452.py b/creator/migrations/0007_auto_20200817_1452.py index ede222e..4dfe76a 100644 --- a/creator/migrations/0007_auto_20200817_1452.py +++ b/creator/migrations/0007_auto_20200817_1452.py @@ -6,18 +6,18 @@ class Migration(migrations.Migration): dependencies = [ - ('creator', '0006_auto_20200817_1417'), + ("creator", "0006_auto_20200817_1417"), ] operations = [ migrations.RenameField( - model_name='product', - old_name='documentation_Devs', - new_name='documentation_Devs_Link', + model_name="product", + old_name="documentation_Devs", + new_name="documentation_Devs_Link", ), migrations.RenameField( - model_name='product', - old_name='documentation_Users', - new_name='documentation_Users_Link', + model_name="product", + old_name="documentation_Users", + new_name="documentation_Users_Link", ), ] diff --git a/creator/models.py b/creator/models.py index 0800a3e..b8c330f 100644 --- a/creator/models.py +++ b/creator/models.py @@ -19,13 +19,19 @@ class Product(models.Model): demo = models.CharField(null=True, blank=True, max_length=256) contributors = models.TextField() isreleased = models.BooleanField(default=False) - documentation_Users_Link = models.CharField( - null=True, blank=True, max_length=256) - documentation_Devs_Link = models.CharField( - null=True, blank=True, max_length=256) + documentation_Users_Link = models.CharField(null=True, blank=True, max_length=256) + documentation_Devs_Link = models.CharField(null=True, blank=True, max_length=256) slug = models.SlugField(null=True, unique=True, max_length=256) - additional_File = models.FileField(null=True, blank=True, - validators=[FileExtensionValidator(allowed_extensions=['pdf', 'pptx', 'ppt', 'md', 'txt', 'jpeg', 'png'])], upload_to='media') + additional_File = models.FileField( + null=True, + blank=True, + validators=[ + FileExtensionValidator( + allowed_extensions=["pdf", "pptx", "ppt", "md", "txt", "jpeg", "png"] + ) + ], + upload_to="media", + ) def __str__(self): return self.name @@ -35,4 +41,4 @@ def save(self, *args, **kwargs): super().save(*args, **kwargs) def get_absolute_url(self): - return reverse('creator:detail', kwargs={'slug': self.slug}) + return reverse("creator:detail", kwargs={"slug": self.slug}) diff --git a/creator/templatetags/countproducts.py b/creator/templatetags/countproducts.py index 1f8c983..7676054 100644 --- a/creator/templatetags/countproducts.py +++ b/creator/templatetags/countproducts.py @@ -3,6 +3,7 @@ register = template.Library() + @register.simple_tag def count_products_of(user): - return Product.objects.filter(user =user).count() + return Product.objects.filter(user=user).count() diff --git a/creator/tests.py b/creator/tests.py index d29a3a6..3130ccd 100644 --- a/creator/tests.py +++ b/creator/tests.py @@ -3,6 +3,7 @@ from django.urls import reverse from .models import Product from django.contrib.auth.models import User + # Create your tests here. @@ -27,35 +28,35 @@ def test_list_view_works_correctly(self): """ The view must contain the creator's products """ - user = create_user(username='TestUser', password='test000') - self.client.login(username='TestUser', password='test000') - create_product(name='TestProduct1', user=user) - create_product(name='TestProduct2', user=user) - response = self.client.get(reverse('creator:list')) - self.assertContains(response, 'TestProduct1') - self.assertContains(response, 'TestProduct2') + user = create_user(username="TestUser", password="test000") + self.client.login(username="TestUser", password="test000") + create_product(name="TestProduct1", user=user) + create_product(name="TestProduct2", user=user) + response = self.client.get(reverse("creator:list")) + self.assertContains(response, "TestProduct1") + self.assertContains(response, "TestProduct2") def test_creator_can_see_only_their_product(self): """ A creator can only see their product """ - user1 = create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') + user1 = create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") - self.client.login(username='TestUser1', password='test000') - create_product(name='TestProduct1', user=user1) - create_product(name='TestProduct2', user=user2) - response = self.client.get(reverse('creator:list')) - self.assertContains(response, 'TestProduct1') - self.assertNotContains(response, 'TestProduct2') + self.client.login(username="TestUser1", password="test000") + create_product(name="TestProduct1", user=user1) + create_product(name="TestProduct2", user=user2) + response = self.client.get(reverse("creator:list")) + self.assertContains(response, "TestProduct1") + self.assertNotContains(response, "TestProduct2") def test_list_view_unauth_user_gets_redirected(self): """ The view must redirect unauthenticated users """ - user = create_user(username='TestUser', password='test000') - create_product(name='TestProduct1', user=user) - response = self.client.get(reverse('creator:list')) + user = create_user(username="TestUser", password="test000") + create_product(name="TestProduct1", user=user) + response = self.client.get(reverse("creator:list")) self.assertNotEquals(response.status_code, 200) @@ -68,19 +69,31 @@ def test_unauthenticated_user_cannot_make_a_product(self): Unauthenticated user shouldn't be able to make a product """ self.client.post( - reverse('creator:create'), - {'name': 'Test Product', 'description': 'Test', 'category': 'Test cat', 'contributors': 'None'}) + reverse("creator:create"), + { + "name": "Test Product", + "description": "Test", + "category": "Test cat", + "contributors": "None", + }, + ) self.assertEquals(Product.objects.all().count(), 0) def test_authenticated_user_can_make_a_product(self): """ Authenticateded user should be able to succesfully make a product """ - create_user(username='TestUser', password='test000') - self.client.login(username='TestUser', password='test000') + create_user(username="TestUser", password="test000") + self.client.login(username="TestUser", password="test000") self.client.post( - reverse('creator:create'), - {'name': 'Test Product', 'description': 'Test', 'category': 'Test cat', 'contributors': 'None'}) + reverse("creator:create"), + { + "name": "Test Product", + "description": "Test", + "category": "Test cat", + "contributors": "None", + }, + ) self.assertEquals(Product.objects.all().count(), 1) @@ -92,23 +105,23 @@ def test_correct_user_can_delete(self): """ Author of the product should be able to delete the product """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user1) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user1) # User1 created the product and they will try to delete it - self.client.post(reverse("creator:delete", kwargs={'slug': product.slug})) + self.client.post(reverse("creator:delete", kwargs={"slug": product.slug})) self.assertEquals(Product.objects.all().count(), 0) def test_incorrect_user_cannot_delete(self): """ If user is not author of the product they shouldn't be able to delete the product """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user2) + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user2) # User2 created the product and user1 will try to delete it - self.client.post(reverse("creator:delete", kwargs={'slug': product.slug})) + self.client.post(reverse("creator:delete", kwargs={"slug": product.slug})) self.assertEquals(Product.objects.all().count(), 1) @@ -120,27 +133,33 @@ def test_correct_user_can_view(self): """ Author of the product should be able to see the Product """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user1) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user1) # User1 created the product and they will try to see it - response = self.client.get(reverse("creator:detail", kwargs={'slug': product.slug})) - self.assertContains(response, 'TestProduct1') + response = self.client.get( + reverse("creator:detail", kwargs={"slug": product.slug}) + ) + self.assertContains(response, "TestProduct1") def test_incorrect_user_can_also_view(self): """ If user is not author of the product they should also be able to view the product """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user2) + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user2) # User2 created the product and user1 will try to view it - response = self.client.get(reverse("creator:detail", kwargs={'slug': product.slug})) - self.assertContains(response, 'TestProduct1') + response = self.client.get( + reverse("creator:detail", kwargs={"slug": product.slug}) + ) + self.assertContains(response, "TestProduct1") self.client.logout() - response = self.client.get(reverse("creator:detail", kwargs={'slug': product.slug})) - self.assertContains(response, 'TestProduct1') + response = self.client.get( + reverse("creator:detail", kwargs={"slug": product.slug}) + ) + self.assertContains(response, "TestProduct1") class ProductUpdateViewTests(TestCase): @@ -151,35 +170,37 @@ def test_correct_user_can_update(self): """ Creator of the product should be able to succesfully update the product """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user1) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user1) # User1 created the product and they will try to update it - self.client.post(reverse( - "creator:update", - kwargs={'slug': product.slug}), - {'name': 'Updated_test_product', - 'description': 'test_description', - 'category': 'CS', - 'contributors': 'None'}) - self.assertEqual(Product.objects.all()[0].name, 'Updated_test_product') + self.client.post( + reverse("creator:update", kwargs={"slug": product.slug}), + { + "name": "Updated_test_product", + "description": "test_description", + "category": "CS", + "contributors": "None", + }, + ) + self.assertEqual(Product.objects.all()[0].name, "Updated_test_product") def test_incorrect_user_cannot_update(self): """ If user is not author of the product they shouldn't be able to update the product """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - product = create_product(name='TestProduct1', user=user2) + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + product = create_product(name="TestProduct1", user=user2) # User2 created the product and user1 will try to update it - self.client.post(reverse( - "creator:update", - kwargs={'slug': product.slug}), + self.client.post( + reverse("creator:update", kwargs={"slug": product.slug}), { - 'name': 'Updated_test_product', - 'description': 'test_description', - 'category': 'CS', - 'contributors': 'None' - }) - self.assertNotEqual(Product.objects.all()[0].name, 'Updated_test_product') + "name": "Updated_test_product", + "description": "test_description", + "category": "CS", + "contributors": "None", + }, + ) + self.assertNotEqual(Product.objects.all()[0].name, "Updated_test_product") diff --git a/creator/urls.py b/creator/urls.py index dfab658..4406cde 100644 --- a/creator/urls.py +++ b/creator/urls.py @@ -1,15 +1,18 @@ from django.urls import path -from .views import (ProductListView, ProductDetailView, - ProductCreateView, ProductUpdateView, ProductDeleteView, - ) -app_name = 'creator' +from .views import ( + ProductListView, + ProductDetailView, + ProductCreateView, + ProductUpdateView, + ProductDeleteView, +) + +app_name = "creator" urlpatterns = [ - path('', ProductListView.as_view(), name='list'), - path('new/', ProductCreateView.as_view(), name='create'), - path('/', ProductDetailView.as_view(), name='detail'), - path('/update/', - ProductUpdateView.as_view(), name='update'), - path('/delete/', - ProductDeleteView.as_view(), name='delete') + path("", ProductListView.as_view(), name="list"), + path("new/", ProductCreateView.as_view(), name="create"), + path("/", ProductDetailView.as_view(), name="detail"), + path("/update/", ProductUpdateView.as_view(), name="update"), + path("/delete/", ProductDeleteView.as_view(), name="delete"), ] diff --git a/creator/views.py b/creator/views.py index 771d2f7..fa0f507 100644 --- a/creator/views.py +++ b/creator/views.py @@ -33,35 +33,55 @@ class ProductDetailView(PageTitleMixin, generic.DetailView): context_object_name = "product" -class ProductCreateView(PageTitleMixin, LoginRequiredMixin, - generic.CreateView): +class ProductCreateView(PageTitleMixin, LoginRequiredMixin, generic.CreateView): model = Product title = "Create Product" template_name = "creator/product_form.html" - fields = ['name', 'description', 'category', 'github_Repo_Link', - 'producthunt', 'youtube_videoid', - 'linkedin', 'demo', 'contributors', 'isreleased', - 'documentation_Users_Link', 'documentation_Devs_Link'] + fields = [ + "name", + "description", + "category", + "github_Repo_Link", + "producthunt", + "youtube_videoid", + "linkedin", + "demo", + "contributors", + "isreleased", + "documentation_Users_Link", + "documentation_Devs_Link", + ] context_object_name = "product" - success_url = reverse_lazy('creator:list') + success_url = reverse_lazy("creator:list") def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form) -class ProductUpdateView(PageTitleMixin, LoginRequiredMixin, - UserPassesTestMixin, generic.UpdateView): +class ProductUpdateView( + PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, generic.UpdateView +): model = Product title = "Update Product" template_name = "creator/product_form.html" - fields = ['name', 'description', 'category', 'github_Repo_Link', - 'producthunt', 'youtube_videoid', - 'linkedin', 'demo', 'contributors', 'isreleased', - 'documentation_Users_Link', 'documentation_Devs_Link'] + fields = [ + "name", + "description", + "category", + "github_Repo_Link", + "producthunt", + "youtube_videoid", + "linkedin", + "demo", + "contributors", + "isreleased", + "documentation_Users_Link", + "documentation_Devs_Link", + ] context_object_name = "product" - success_url = reverse_lazy('creator:list') + success_url = reverse_lazy("creator:list") def form_valid(self, form): form.instance.user = self.request.user @@ -73,13 +93,14 @@ def test_func(self): return True -class ProductDeleteView(PageTitleMixin, LoginRequiredMixin, - UserPassesTestMixin, generic.DeleteView): +class ProductDeleteView( + PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, generic.DeleteView +): model = Product title = "Delete Product" template_name = "creator/product_confirm_delete.html" context_object_name = "product" - success_url = reverse_lazy('creator:list') + success_url = reverse_lazy("creator:list") def test_func(self): product = self.get_object() diff --git a/devmanage.py b/devmanage.py index 2d2a5b6..312b6f7 100644 --- a/devmanage.py +++ b/devmanage.py @@ -5,7 +5,7 @@ def main(): - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'domecode.devsettings') + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "domecode.devsettings") try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -17,5 +17,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/domecode/asgi.py b/domecode/asgi.py index d912fa0..ea3b619 100755 --- a/domecode/asgi.py +++ b/domecode/asgi.py @@ -11,6 +11,6 @@ from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'geddit.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "geddit.settings") application = get_asgi_application() diff --git a/domecode/devsettings.py b/domecode/devsettings.py index cbb4ec8..03f46cb 100644 --- a/domecode/devsettings.py +++ b/domecode/devsettings.py @@ -1,5 +1,6 @@ import os from decouple import config + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -8,117 +9,106 @@ # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = config('SECRET_KEY') # hc +SECRET_KEY = config("SECRET_KEY") # hc # SECURITY WARNING: don't run with debug turned on in production! # hc DEBUG = True -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ["*"] # Application definition INSTALLED_APPS = [ # myapps - 'users.apps.UsersConfig', - 'notes.apps.NotesConfig', - 'todo.apps.TodoConfig', - 'forum.apps.ForumConfig', - 'coder.apps.CoderConfig', - 'quizzes.apps.QuizzesConfig', - 'resources.apps.ResourcesConfig', - 'creator.apps.CreatorConfig', - 'fusion.apps.FusionConfig', + "users.apps.UsersConfig", + "notes.apps.NotesConfig", + "todo.apps.TodoConfig", + "forum.apps.ForumConfig", + "coder.apps.CoderConfig", + "quizzes.apps.QuizzesConfig", + "resources.apps.ResourcesConfig", + "creator.apps.CreatorConfig", + "fusion.apps.FusionConfig", # crispy - 'crispy_forms', + "crispy_forms", # default - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - - 'six', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "six", # rest - 'rest_framework', - 'rest_framework.authtoken', + "rest_framework", + "rest_framework.authtoken", # oauth - 'social_django', + "social_django", # ckeditor - 'ckeditor', - 'ckeditor_uploader', - 'storages', - + "ckeditor", + "ckeditor_uploader", + "storages", ] MIDDLEWARE = [ - - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", # OAUTH - 'social_django.middleware.SocialAuthExceptionMiddleware', - - + "social_django.middleware.SocialAuthExceptionMiddleware", ] -HONEYBADGER = { - 'API_KEY': '60aaca87' -} +HONEYBADGER = {"API_KEY": "60aaca87"} -ROOT_URLCONF = 'domecode.urls' +ROOT_URLCONF = "domecode.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - - 'social_django.context_processors.backends', # OAUTH - 'social_django.context_processors.login_redirect', # OAUTH - + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "social_django.context_processors.backends", # OAUTH + "social_django.context_processors.login_redirect", # OAUTH ], - }, }, ] -WSGI_APPLICATION = 'domecode.wsgi.application' +WSGI_APPLICATION = "domecode.wsgi.application" # Database # https://docs.djangoproject.com/en/3.0/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - 'HOST': config('DB_HOST'), + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + "HOST": config("DB_HOST"), } } AUTHENTICATION_BACKENDS = ( - 'social_core.backends.github.GithubOAuth2', - 'social_core.backends.google.GoogleOAuth2', - 'django.contrib.auth.backends.ModelBackend', + "social_core.backends.github.GithubOAuth2", + "social_core.backends.google.GoogleOAuth2", + "django.contrib.auth.backends.ModelBackend", ) -SOCIAL_AUTH_GITHUB_KEY = config('SOCIAL_AUTH_GITHUB_KEY') # hc -SOCIAL_AUTH_GITHUB_SECRET = config('SOCIAL_AUTH_GITHUB_SECRET') # hc -SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = config('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY') # hc -SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = config( - 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET') # hc +SOCIAL_AUTH_GITHUB_KEY = config("SOCIAL_AUTH_GITHUB_KEY") # hc +SOCIAL_AUTH_GITHUB_SECRET = config("SOCIAL_AUTH_GITHUB_SECRET") # hc +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = config("SOCIAL_AUTH_GOOGLE_OAUTH2_KEY") # hc +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = config("SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET") # hc # Password validation @@ -126,39 +116,36 @@ AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - + "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), + "DEFAULT_AUTHENTICATION_CLASSES": ( + "rest_framework.authentication.TokenAuthentication", + "rest_framework.authentication.SessionAuthentication", ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ) } # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'Asia/Kolkata' +TIME_ZONE = "Asia/Kolkata" USE_I18N = True @@ -170,28 +157,26 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ -STATIC_URL = '/static/' -STATIC_ROOT = os.path.join(BASE_DIR, 'notes/static/') -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') -MEDIA_URL = '/media/' +STATIC_URL = "/static/" +STATIC_ROOT = os.path.join(BASE_DIR, "notes/static/") +MEDIA_ROOT = os.path.join(BASE_DIR, "media") +MEDIA_URL = "/media/" -CRISPY_TEMPLATE_PACK = 'bootstrap4' +CRISPY_TEMPLATE_PACK = "bootstrap4" -LOGIN_URL = 'login' +LOGIN_URL = "login" -LOGOUT_URL = 'logout' -LOGOUT_REDIRECT_URL = 'login' +LOGOUT_URL = "logout" +LOGOUT_REDIRECT_URL = "login" CKEDITOR_UPLOAD_PATH = "uploads/" CKEDITOR_CONFIGS = { - 'default': { - 'toolbar': 'auto', # You can change this based on your requirements. - 'width': 'auto', - 'height': 'auto', - 'uiColor': 'moona-lisa' - - + "default": { + "toolbar": "auto", # You can change this based on your requirements. + "width": "auto", + "height": "auto", + "uiColor": "moona-lisa", }, } """ @@ -202,49 +187,46 @@ def get_cache(): import os + try: - servers = os.environ['MEMCACHIER_SERVERS'] - username = os.environ['MEMCACHIER_USERNAME'] - password = os.environ['MEMCACHIER_PASSWORD'] + servers = os.environ["MEMCACHIER_SERVERS"] + username = os.environ["MEMCACHIER_USERNAME"] + password = os.environ["MEMCACHIER_PASSWORD"] return { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', + "default": { + "BACKEND": "django.core.cache.backends.memcached.PyLibMCCache", # TIMEOUT is not the connection timeout! It's the default expiration # timeout that should be applied to keys! Setting it to `None` # disables expiration. - 'TIMEOUT': None, - 'LOCATION': servers, - 'OPTIONS': { - 'binary': True, - 'username': username, - 'password': password, - 'behaviors': { + "TIMEOUT": None, + "LOCATION": servers, + "OPTIONS": { + "binary": True, + "username": username, + "password": password, + "behaviors": { # Enable faster IO - 'no_block': True, - 'tcp_nodelay': True, + "no_block": True, + "tcp_nodelay": True, # Keep connection alive - 'tcp_keepalive': True, + "tcp_keepalive": True, # Timeout settings - 'connect_timeout': 2000, # ms - 'send_timeout': 750 * 1000, # us - 'receive_timeout': 750 * 1000, # us - '_poll_timeout': 2000, # ms + "connect_timeout": 2000, # ms + "send_timeout": 750 * 1000, # us + "receive_timeout": 750 * 1000, # us + "_poll_timeout": 2000, # ms # Better failover - 'ketama': True, - 'remove_failed': 1, - 'retry_timeout': 2, - 'dead_timeout': 30, - } - } + "ketama": True, + "remove_failed": 1, + "retry_timeout": 2, + "dead_timeout": 30, + }, + }, } } except: - return { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache' - } - } + return {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}} CACHES = get_cache() -JUDGE0_RAPID_API_KEY = config('JUDGE0_RAPID_API_KEY') +JUDGE0_RAPID_API_KEY = config("JUDGE0_RAPID_API_KEY") diff --git a/domecode/settings.py b/domecode/settings.py index adcd4d9..487e0c4 100644 --- a/domecode/settings.py +++ b/domecode/settings.py @@ -1,6 +1,7 @@ import os from decouple import config import django_heroku + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -9,119 +10,108 @@ # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = config('SECRET_KEY') # hc +SECRET_KEY = config("SECRET_KEY") # hc # SECURITY WARNING: don't run with debug turned on in production! # hc DEBUG = False -ALLOWED_HOSTS = ['.domecode.com'] +ALLOWED_HOSTS = [".domecode.com"] # Application definition INSTALLED_APPS = [ # myapps - 'users.apps.UsersConfig', - 'notes.apps.NotesConfig', - 'todo.apps.TodoConfig', - 'forum.apps.ForumConfig', - 'coder.apps.CoderConfig', - 'quizzes.apps.QuizzesConfig', - 'resources.apps.ResourcesConfig', - 'creator.apps.CreatorConfig', - 'fusion.apps.FusionConfig', + "users.apps.UsersConfig", + "notes.apps.NotesConfig", + "todo.apps.TodoConfig", + "forum.apps.ForumConfig", + "coder.apps.CoderConfig", + "quizzes.apps.QuizzesConfig", + "resources.apps.ResourcesConfig", + "creator.apps.CreatorConfig", + "fusion.apps.FusionConfig", # crispy - 'crispy_forms', + "crispy_forms", # default - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - - 'six', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "six", # rest - 'rest_framework', - 'rest_framework.authtoken', + "rest_framework", + "rest_framework.authtoken", # oauth - 'social_django', + "social_django", # ckeditor - 'ckeditor', - 'ckeditor_uploader', - 'storages', - + "ckeditor", + "ckeditor_uploader", + "storages", ] MIDDLEWARE = [ # honeybadger - 'honeybadger.middleware.DjangoHoneybadgerMiddleware', - - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "honeybadger.middleware.DjangoHoneybadgerMiddleware", + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", # OAUTH - 'social_django.middleware.SocialAuthExceptionMiddleware', - - + "social_django.middleware.SocialAuthExceptionMiddleware", ] -HONEYBADGER = { - 'API_KEY': '60aaca87' -} +HONEYBADGER = {"API_KEY": "60aaca87"} -ROOT_URLCONF = 'domecode.urls' +ROOT_URLCONF = "domecode.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - - 'social_django.context_processors.backends', # OAUTH - 'social_django.context_processors.login_redirect', # OAUTH - + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "social_django.context_processors.backends", # OAUTH + "social_django.context_processors.login_redirect", # OAUTH ], - }, }, ] -WSGI_APPLICATION = 'domecode.wsgi.application' +WSGI_APPLICATION = "domecode.wsgi.application" # Database # https://docs.djangoproject.com/en/3.0/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - 'HOST': config('DB_HOST'), + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + "HOST": config("DB_HOST"), } } AUTHENTICATION_BACKENDS = ( - 'social_core.backends.github.GithubOAuth2', - 'social_core.backends.google.GoogleOAuth2', - 'django.contrib.auth.backends.ModelBackend', + "social_core.backends.github.GithubOAuth2", + "social_core.backends.google.GoogleOAuth2", + "django.contrib.auth.backends.ModelBackend", ) -SOCIAL_AUTH_GITHUB_KEY = config('SOCIAL_AUTH_GITHUB_KEY') # hc -SOCIAL_AUTH_GITHUB_SECRET = config('SOCIAL_AUTH_GITHUB_SECRET') # hc -SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = config('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY') # hc -SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = config( - 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET') # hc +SOCIAL_AUTH_GITHUB_KEY = config("SOCIAL_AUTH_GITHUB_KEY") # hc +SOCIAL_AUTH_GITHUB_SECRET = config("SOCIAL_AUTH_GITHUB_SECRET") # hc +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = config("SOCIAL_AUTH_GOOGLE_OAUTH2_KEY") # hc +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = config("SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET") # hc # Password validation @@ -129,39 +119,36 @@ AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - + "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), + "DEFAULT_AUTHENTICATION_CLASSES": ( + "rest_framework.authentication.TokenAuthentication", + "rest_framework.authentication.SessionAuthentication", ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ) } # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'Asia/Kolkata' +TIME_ZONE = "Asia/Kolkata" USE_I18N = True @@ -173,28 +160,26 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ -STATIC_URL = '/static/' -STATIC_ROOT = os.path.join(BASE_DIR, 'notes/static/') -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') -MEDIA_URL = '/media/' +STATIC_URL = "/static/" +STATIC_ROOT = os.path.join(BASE_DIR, "notes/static/") +MEDIA_ROOT = os.path.join(BASE_DIR, "media") +MEDIA_URL = "/media/" -CRISPY_TEMPLATE_PACK = 'bootstrap4' +CRISPY_TEMPLATE_PACK = "bootstrap4" -LOGIN_URL = 'login' +LOGIN_URL = "login" -LOGOUT_URL = 'logout' -LOGOUT_REDIRECT_URL = 'login' +LOGOUT_URL = "logout" +LOGOUT_REDIRECT_URL = "login" CKEDITOR_UPLOAD_PATH = "uploads/" CKEDITOR_CONFIGS = { - 'default': { - 'toolbar': 'auto', # You can change this based on your requirements. - 'width': 'auto', - 'height': 'auto', - 'uiColor': 'moona-lisa' - - + "default": { + "toolbar": "auto", # You can change this based on your requirements. + "width": "auto", + "height": "auto", + "uiColor": "moona-lisa", }, } """ @@ -202,76 +187,73 @@ """ -SECURE_HSTS_SECONDS = config('SECURE_HSTS_SECONDS') +SECURE_HSTS_SECONDS = config("SECURE_HSTS_SECONDS") SECURE_SSL_REDIRECT = True SECURE_HSTS_INCLUDE_SUBDOMAINS = True -SESSION_COOKIE_SECURE = config('SESSION_COOKIE_SECURE', cast=bool) -CSRF_COOKIE_SECURE = config('CSRF_COOKIE_SECURE', cast=bool) +SESSION_COOKIE_SECURE = config("SESSION_COOKIE_SECURE", cast=bool) +CSRF_COOKIE_SECURE = config("CSRF_COOKIE_SECURE", cast=bool) SECURE_HSTS_PRELOAD = True -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") -AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID') # heroku config -AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY') # hc -AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME') # hc -AWS_S3_REGION_NAME = 'ap-south-1' # change to your region -AWS_S3_SIGNATURE_VERSION = 's3v4' +AWS_ACCESS_KEY_ID = config("AWS_ACCESS_KEY_ID") # heroku config +AWS_SECRET_ACCESS_KEY = config("AWS_SECRET_ACCESS_KEY") # hc +AWS_STORAGE_BUCKET_NAME = config("AWS_STORAGE_BUCKET_NAME") # hc +AWS_S3_REGION_NAME = "ap-south-1" # change to your region +AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = None -DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' +DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" django_heroku.settings(locals()) def get_cache(): import os + try: - servers = os.environ['MEMCACHIER_SERVERS'] - username = os.environ['MEMCACHIER_USERNAME'] - password = os.environ['MEMCACHIER_PASSWORD'] + servers = os.environ["MEMCACHIER_SERVERS"] + username = os.environ["MEMCACHIER_USERNAME"] + password = os.environ["MEMCACHIER_PASSWORD"] return { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', + "default": { + "BACKEND": "django.core.cache.backends.memcached.PyLibMCCache", # TIMEOUT is not the connection timeout! It's the default # expirationtimeout that should be applied to keys! # Setting it to `None` # disables expiration. - 'TIMEOUT': None, - 'LOCATION': servers, - 'OPTIONS': { - 'binary': True, - 'username': username, - 'password': password, - 'behaviors': { + "TIMEOUT": None, + "LOCATION": servers, + "OPTIONS": { + "binary": True, + "username": username, + "password": password, + "behaviors": { # Enable faster IO - 'no_block': True, - 'tcp_nodelay': True, + "no_block": True, + "tcp_nodelay": True, # Keep connection alive - 'tcp_keepalive': True, + "tcp_keepalive": True, # Timeout settings - 'connect_timeout': 2000, # ms - 'send_timeout': 750 * 1000, # us - 'receive_timeout': 750 * 1000, # us - '_poll_timeout': 2000, # ms + "connect_timeout": 2000, # ms + "send_timeout": 750 * 1000, # us + "receive_timeout": 750 * 1000, # us + "_poll_timeout": 2000, # ms # Better failover - 'ketama': True, - 'remove_failed': 1, - 'retry_timeout': 2, - 'dead_timeout': 30, - } - } + "ketama": True, + "remove_failed": 1, + "retry_timeout": 2, + "dead_timeout": 30, + }, + }, } } except: - return { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache' - } - } + return {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}} CACHES = get_cache() -JUDGE0_RAPID_API_KEY = config('JUDGE0_RAPID_API_KEY') +JUDGE0_RAPID_API_KEY = config("JUDGE0_RAPID_API_KEY") diff --git a/domecode/urls.py b/domecode/urls.py index 2ce327e..2ba6b9b 100755 --- a/domecode/urls.py +++ b/domecode/urls.py @@ -2,7 +2,7 @@ from django.contrib.auth import views as auth_views from django.urls import path, include from django.conf import settings -from .import devsettings +from . import devsettings from django.conf.urls.static import static from decouple import config @@ -10,34 +10,33 @@ admin.autodiscover() urlpatterns = [ - path(config('ADMIN_URL'), admin.site.urls), - path('oauth/', include('social_django.urls', namespace='social')), - path('profile/login/', - auth_views.LoginView.as_view(template_name='users/login.html'), name='login'), - path('logout/', auth_views.LogoutView.as_view(), name='logout'), - path('', include('users.urls')), - path('', include('notes.urls')), - path('', include('forum.urls')), - path('todo/', include('todo.urls')), - path('tracks/', include('resources.urls')), - path('practice/', include('coder.urls')), - path('ckeditor/', include('ckeditor_uploader.urls')), - path('quiz/', include('quizzes.urls')), - path('products/', include('creator.urls')), - path('fusion/', include('fusion.urls')), + path(config("ADMIN_URL"), admin.site.urls), + path("oauth/", include("social_django.urls", namespace="social")), + path( + "profile/login/", + auth_views.LoginView.as_view(template_name="users/login.html"), + name="login", + ), + path("logout/", auth_views.LogoutView.as_view(), name="logout"), + path("", include("users.urls")), + path("", include("notes.urls")), + path("", include("forum.urls")), + path("todo/", include("todo.urls")), + path("tracks/", include("resources.urls")), + path("practice/", include("coder.urls")), + path("ckeditor/", include("ckeditor_uploader.urls")), + path("quiz/", include("quizzes.urls")), + path("products/", include("creator.urls")), + path("fusion/", include("fusion.urls")), # REST FRAMEWORK URLS - path('api/todo/', include('todo.api.urls', 'todo_api')), - path('api/notes/', include('notes.api.urls', 'notes_api')), + path("api/todo/", include("todo.api.urls", "todo_api")), + path("api/notes/", include("notes.api.urls", "notes_api")), ] if settings.DEBUG: - urlpatterns += static(settings.MEDIA_URL, - document_root=settings.MEDIA_ROOT) - urlpatterns += static(settings.STATIC_URL, - document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) elif devsettings.DEBUG: - urlpatterns += static(devsettings.MEDIA_URL, - document_root=devsettings.MEDIA_ROOT) - urlpatterns += static(settings.STATIC_URL, - document_root=devsettings.STATIC_ROOT) + urlpatterns += static(devsettings.MEDIA_URL, document_root=devsettings.MEDIA_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=devsettings.STATIC_ROOT) diff --git a/domecode/wsgi.py b/domecode/wsgi.py index 64b24b1..261d320 100755 --- a/domecode/wsgi.py +++ b/domecode/wsgi.py @@ -11,6 +11,6 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'domecode.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "domecode.settings") application = get_wsgi_application() diff --git a/forum/admin.py b/forum/admin.py index 42fa6bd..762515b 100644 --- a/forum/admin.py +++ b/forum/admin.py @@ -1,6 +1,7 @@ from forum.models import Query from django.contrib import admin from .models import * + # Register your models here. admin.site.register(Query) admin.site.register(Answer) diff --git a/forum/apps.py b/forum/apps.py index 99ee7e7..39207e3 100644 --- a/forum/apps.py +++ b/forum/apps.py @@ -2,4 +2,4 @@ class ForumConfig(AppConfig): - name = 'forum' + name = "forum" diff --git a/forum/migrations/0001_initial.py b/forum/migrations/0001_initial.py index f58acb1..a0ae4cb 100644 --- a/forum/migrations/0001_initial.py +++ b/forum/migrations/0001_initial.py @@ -16,28 +16,79 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Query', + name="Query", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=240)), - ('content', ckeditor.fields.RichTextField(blank=True, null=True)), - ('category', models.CharField(max_length=25)), - ('created', models.DateTimeField(auto_now_add=True)), - ('last_modified', models.DateTimeField(auto_now=True)), - ('likes', models.ManyToManyField(blank=True, default=None, related_name='query_likes', to=settings.AUTH_USER_MODEL)), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=240)), + ("content", ckeditor.fields.RichTextField(blank=True, null=True)), + ("category", models.CharField(max_length=25)), + ("created", models.DateTimeField(auto_now_add=True)), + ("last_modified", models.DateTimeField(auto_now=True)), + ( + "likes", + models.ManyToManyField( + blank=True, + default=None, + related_name="query_likes", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Answer', + name="Answer", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content', ckeditor.fields.RichTextField()), - ('created', models.DateTimeField(auto_now_add=True)), - ('last_modified', models.DateTimeField(auto_now=True)), - ('likes', models.ManyToManyField(blank=True, default=None, related_name='answer_likes', to=settings.AUTH_USER_MODEL)), - ('query', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Query')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("content", ckeditor.fields.RichTextField()), + ("created", models.DateTimeField(auto_now_add=True)), + ("last_modified", models.DateTimeField(auto_now=True)), + ( + "likes", + models.ManyToManyField( + blank=True, + default=None, + related_name="answer_likes", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "query", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="forum.Query" + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/forum/migrations/0002_query_slug.py b/forum/migrations/0002_query_slug.py index ea7b63d..f20252e 100644 --- a/forum/migrations/0002_query_slug.py +++ b/forum/migrations/0002_query_slug.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0001_initial'), + ("forum", "0001_initial"), ] operations = [ migrations.AddField( - model_name='query', - name='slug', + model_name="query", + name="slug", field=models.SlugField(null=True, unique=True), ), ] diff --git a/forum/migrations/0003_answer_slug.py b/forum/migrations/0003_answer_slug.py index 314d6d7..7e662a8 100644 --- a/forum/migrations/0003_answer_slug.py +++ b/forum/migrations/0003_answer_slug.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0002_query_slug'), + ("forum", "0002_query_slug"), ] operations = [ migrations.AddField( - model_name='answer', - name='slug', + model_name="answer", + name="slug", field=models.SlugField(null=True, unique=True), ), ] diff --git a/forum/migrations/0004_auto_20200725_0400.py b/forum/migrations/0004_auto_20200725_0400.py index 33ee386..4b615bb 100644 --- a/forum/migrations/0004_auto_20200725_0400.py +++ b/forum/migrations/0004_auto_20200725_0400.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0003_answer_slug'), + ("forum", "0003_answer_slug"), ] operations = [ migrations.AlterField( - model_name='query', - name='category', - field=models.CharField(choices=[('GEN', 'General Development'), ('WEB', 'Web Development'), ('CS', 'Computer Science'), ('CAS', 'Casual Development')], default='GEN', max_length=3), + model_name="query", + name="category", + field=models.CharField( + choices=[ + ("GEN", "General Development"), + ("WEB", "Web Development"), + ("CS", "Computer Science"), + ("CAS", "Casual Development"), + ], + default="GEN", + max_length=3, + ), ), ] diff --git a/forum/migrations/0005_auto_20200725_0401.py b/forum/migrations/0005_auto_20200725_0401.py index 6e066c2..3e2037f 100644 --- a/forum/migrations/0005_auto_20200725_0401.py +++ b/forum/migrations/0005_auto_20200725_0401.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0004_auto_20200725_0400'), + ("forum", "0004_auto_20200725_0400"), ] operations = [ migrations.AlterField( - model_name='query', - name='category', - field=models.CharField(choices=[('GEN', 'General Development'), ('WEB', 'Web Development'), ('CS', 'Computer Science'), ('ABT', 'About DomeCode')], default='GEN', max_length=3), + model_name="query", + name="category", + field=models.CharField( + choices=[ + ("GEN", "General Development"), + ("WEB", "Web Development"), + ("CS", "Computer Science"), + ("ABT", "About DomeCode"), + ], + default="GEN", + max_length=3, + ), ), ] diff --git a/forum/migrations/0006_auto_20200725_0406.py b/forum/migrations/0006_auto_20200725_0406.py index b474579..83ec181 100644 --- a/forum/migrations/0006_auto_20200725_0406.py +++ b/forum/migrations/0006_auto_20200725_0406.py @@ -6,13 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0005_auto_20200725_0401'), + ("forum", "0005_auto_20200725_0401"), ] operations = [ migrations.AlterField( - model_name='query', - name='category', - field=models.CharField(choices=[('General Development', 'General Development'), ('Web Development', 'Web Development'), ('CS', 'Computer Science'), ('About DomeCode', 'About DomeCode')], default='GEN', max_length=30), + model_name="query", + name="category", + field=models.CharField( + choices=[ + ("General Development", "General Development"), + ("Web Development", "Web Development"), + ("CS", "Computer Science"), + ("About DomeCode", "About DomeCode"), + ], + default="GEN", + max_length=30, + ), ), ] diff --git a/forum/migrations/0007_answer_isaccepted.py b/forum/migrations/0007_answer_isaccepted.py index 9b3d63b..d2182d4 100644 --- a/forum/migrations/0007_answer_isaccepted.py +++ b/forum/migrations/0007_answer_isaccepted.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0006_auto_20200725_0406'), + ("forum", "0006_auto_20200725_0406"), ] operations = [ migrations.AddField( - model_name='answer', - name='isaccepted', + model_name="answer", + name="isaccepted", field=models.BooleanField(default=False), ), ] diff --git a/forum/migrations/0008_comment.py b/forum/migrations/0008_comment.py index a5ce9b5..664f2bc 100644 --- a/forum/migrations/0008_comment.py +++ b/forum/migrations/0008_comment.py @@ -10,20 +10,40 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('forum', '0007_answer_isaccepted'), + ("forum", "0007_answer_isaccepted"), ] operations = [ migrations.CreateModel( - name='Comment', + name="Comment", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content', ckeditor.fields.RichTextField()), - ('created', models.DateTimeField(auto_now_add=True)), - ('last_modified', models.DateTimeField(auto_now=True)), - ('slug', models.SlugField(null=True, unique=True)), - ('answer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Answer')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("content", ckeditor.fields.RichTextField()), + ("created", models.DateTimeField(auto_now_add=True)), + ("last_modified", models.DateTimeField(auto_now=True)), + ("slug", models.SlugField(null=True, unique=True)), + ( + "answer", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="forum.Answer" + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/forum/migrations/0009_auto_20200803_0125.py b/forum/migrations/0009_auto_20200803_0125.py index 0a26b58..fe9b47f 100644 --- a/forum/migrations/0009_auto_20200803_0125.py +++ b/forum/migrations/0009_auto_20200803_0125.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0008_comment'), + ("forum", "0008_comment"), ] operations = [ migrations.AlterField( - model_name='comment', - name='slug', + model_name="comment", + name="slug", field=models.SlugField(null=True), ), ] diff --git a/forum/migrations/0010_auto_20200805_2110.py b/forum/migrations/0010_auto_20200805_2110.py index 06c4151..c5f80bb 100644 --- a/forum/migrations/0010_auto_20200805_2110.py +++ b/forum/migrations/0010_auto_20200805_2110.py @@ -6,23 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('forum', '0009_auto_20200803_0125'), + ("forum", "0009_auto_20200803_0125"), ] operations = [ migrations.AlterField( - model_name='answer', - name='slug', + model_name="answer", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), migrations.AlterField( - model_name='comment', - name='slug', + model_name="comment", + name="slug", field=models.SlugField(max_length=256, null=True), ), migrations.AlterField( - model_name='query', - name='slug', + model_name="query", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/forum/models.py b/forum/models.py index cf0f8fa..d0bd5a5 100644 --- a/forum/models.py +++ b/forum/models.py @@ -9,19 +9,19 @@ class Query(models.Model): CATEGORY = [ - ('General Development', 'General Development'), - ('Web Development', 'Web Development'), - ('CS', 'Computer Science'), - ('About DomeCode', 'About DomeCode') + ("General Development", "General Development"), + ("Web Development", "Web Development"), + ("CS", "Computer Science"), + ("About DomeCode", "About DomeCode"), ] title = models.CharField(max_length=240) - user = models.ForeignKey( - get_user_model(), null=True, on_delete=models.SET_NULL) + user = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL) content = RichTextField(null=True, blank=True) likes = models.ManyToManyField( - User, default=None, blank=True, related_name="query_likes") - category = models.CharField(max_length=30, choices=CATEGORY, default='GEN') + User, default=None, blank=True, related_name="query_likes" + ) + category = models.CharField(max_length=30, choices=CATEGORY, default="GEN") created = models.DateTimeField(auto_now_add=True) last_modified = models.DateTimeField(auto_now=True) slug = models.SlugField(null=True, unique=True, max_length=256) @@ -30,25 +30,25 @@ def __str__(self): return self.title def likes_as_flat_user_id_list(self): - return self.likes.values_list('id', flat=True) + return self.likes.values_list("id", flat=True) def save(self, *args, **kwargs): self.slug = slugify(self.title) super().save(*args, **kwargs) def get_absolute_url(self): - return reverse('forum:detail', kwargs={'slug': self.slug}) + return reverse("forum:detail", kwargs={"slug": self.slug}) class Answer(models.Model): - user = models.ForeignKey( - get_user_model(), null=True, on_delete=models.SET_NULL) + user = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL) query = models.ForeignKey(Query, on_delete=models.CASCADE) content = RichTextField() created = models.DateTimeField(auto_now_add=True) last_modified = models.DateTimeField(auto_now=True) likes = models.ManyToManyField( - User, default=None, blank=True, related_name="answer_likes") + User, default=None, blank=True, related_name="answer_likes" + ) slug = models.SlugField(null=True, unique=True, max_length=256) isaccepted = models.BooleanField(default=False) @@ -58,12 +58,11 @@ def save(self, *args, **kwargs): super().save(*args, **kwargs) def get_absolute_url(self): - return reverse('forum:detail', kwargs={'slug': self.query.slug}) + return reverse("forum:detail", kwargs={"slug": self.query.slug}) class Comment(models.Model): - user = models.ForeignKey( - get_user_model(), null=True, on_delete=models.SET_NULL) + user = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL) answer = models.ForeignKey(Answer, on_delete=models.CASCADE) content = RichTextField() created = models.DateTimeField(auto_now_add=True) @@ -71,7 +70,7 @@ class Comment(models.Model): slug = models.SlugField(null=True, unique=False, max_length=256) def get_absolute_url(self): - return reverse('forum:detail', kwargs={'slug': self.answer.query.slug}) + return reverse("forum:detail", kwargs={"slug": self.answer.query.slug}) def save(self, *args, **kwargs): uniqueid = get_random_string(length=8) diff --git a/forum/templatetags/forumtags.py b/forum/templatetags/forumtags.py index c951520..e26da72 100644 --- a/forum/templatetags/forumtags.py +++ b/forum/templatetags/forumtags.py @@ -1,12 +1,13 @@ from django import template + register = template.Library() -@register.filter(name='answers', is_safe=True) +@register.filter(name="answers", is_safe=True) def submissions(query): - return query.answer_set.order_by('-last_modified') + return query.answer_set.order_by("-last_modified") @register.filter(name="comments", is_safe=True) def comments(answer): - return answer.comment_set.order_by('last_modified') + return answer.comment_set.order_by("last_modified") diff --git a/forum/urls.py b/forum/urls.py index aeee7b4..4597291 100644 --- a/forum/urls.py +++ b/forum/urls.py @@ -1,45 +1,94 @@ from django.urls import path -from .import views -from .views import (QueryCreateView, QueryListView, QueryUpdateView, QueryDeleteView, QueryDetailView, QueryLikeAPIToggle, QueryLikeToggle, - AnswerCreateView, AnswerDeleteView, AnswerUpdateView, AnswerDetailView, AcceptAnswerView, CommentCreateView, CommentDeleteView, CommentUpdateView, ) +from . import views +from .views import ( + QueryCreateView, + QueryListView, + QueryUpdateView, + QueryDeleteView, + QueryDetailView, + QueryLikeAPIToggle, + QueryLikeToggle, + AnswerCreateView, + AnswerDeleteView, + AnswerUpdateView, + AnswerDetailView, + AcceptAnswerView, + CommentCreateView, + CommentDeleteView, + CommentUpdateView, +) -app_name = 'forum' +app_name = "forum" urlpatterns = [ # forum url - path('forum/', QueryListView.as_view(), name='list'), - path('forum/guidelines', views.guidelines, name='guidelines'), + path("forum/", QueryListView.as_view(), name="list"), + path("forum/guidelines", views.guidelines, name="guidelines"), # query urls - path('forum/query/new/', QueryCreateView.as_view(), name='query-create'), - path('forum/query//', QueryDetailView.as_view(), name='detail'), - path('forum/query//update/', - QueryUpdateView.as_view(), name='query-update'), - path('forum/query//delete/', - QueryDeleteView.as_view(), name='query-delete'), - path('forum/query//like/', - QueryLikeToggle.as_view(), name='query-likes-toggle'), - path('api/forum/query//like/', - QueryLikeAPIToggle.as_view(), name='query-likes-api-toggle'), - + path("forum/query/new/", QueryCreateView.as_view(), name="query-create"), + path("forum/query//", QueryDetailView.as_view(), name="detail"), + path( + "forum/query//update/", + QueryUpdateView.as_view(), + name="query-update", + ), + path( + "forum/query//delete/", + QueryDeleteView.as_view(), + name="query-delete", + ), + path( + "forum/query//like/", + QueryLikeToggle.as_view(), + name="query-likes-toggle", + ), + path( + "api/forum/query//like/", + QueryLikeAPIToggle.as_view(), + name="query-likes-api-toggle", + ), # answer urls - - path('forum/query//answer/create/', - AnswerCreateView.as_view(), name='answer-create'), - path('forum/query//answer//', - AnswerDetailView.as_view(), name='answer-detail'), - path('forum/query//answer/update/', - AnswerUpdateView.as_view(), name='answer-update'), - path('forum/query//answer/delete//', - AnswerDeleteView.as_view(), name='answer-delete'), - path('forum/query//answer/accept//', - AcceptAnswerView.as_view(), name='accept'), + path( + "forum/query//answer/create/", + AnswerCreateView.as_view(), + name="answer-create", + ), + path( + "forum/query//answer//", + AnswerDetailView.as_view(), + name="answer-detail", + ), + path( + "forum/query//answer/update/", + AnswerUpdateView.as_view(), + name="answer-update", + ), + path( + "forum/query//answer/delete//", + AnswerDeleteView.as_view(), + name="answer-delete", + ), + path( + "forum/query//answer/accept//", + AcceptAnswerView.as_view(), + name="accept", + ), # commenturls - path('forum/query//answer//comment/create/', - CommentCreateView.as_view(), name='comment-create'), - path('forum/query//answer//comment/update/', - CommentUpdateView.as_view(), name='comment-update'), - path('forum/query//answer//comment/delete//', - CommentDeleteView.as_view(), name='comment-delete'), + path( + "forum/query//answer//comment/create/", + CommentCreateView.as_view(), + name="comment-create", + ), + path( + "forum/query//answer//comment/update/", + CommentUpdateView.as_view(), + name="comment-update", + ), + path( + "forum/query//answer//comment/delete//", + CommentDeleteView.as_view(), + name="comment-delete", + ), # path('forum/query//answer/like/', # AnswerLikeToggle.as_view(), name='answer-likes-toggle'), # path('api/forum/answer//like/', diff --git a/forum/views.py b/forum/views.py index 1153cdd..0a0b8e0 100644 --- a/forum/views.py +++ b/forum/views.py @@ -12,26 +12,26 @@ def guidelines(request): - return render(request, 'forum/guidelines.html', {'title': 'Forum Guidelines'}) + return render(request, "forum/guidelines.html", {"title": "Forum Guidelines"}) class QueryListView(PageTitleMixin, generic.ListView): model = Query template_name = "forum/query_list.html" paginate_by = 15 - context_object_name = 'query' - ordering = ['-last_modified'] - title = 'Forum' + context_object_name = "query" + ordering = ["-last_modified"] + title = "Forum" def get_queryset(self, *args, **kwargs): object_list = super(QueryListView, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__contains=search) | - Q(content__contains=search) | - Q(category__contains=search) - ).order_by('-last_modified') + Q(title__contains=search) + | Q(content__contains=search) + | Q(category__contains=search) + ).order_by("-last_modified") return object_list else: return object_list @@ -40,24 +40,26 @@ def get_queryset(self, *args, **kwargs): class QueryDetailView(PageTitleMixin, generic.DetailView): model = Query template_name = "forum/query_detail.html" - title = 'Forum' + title = "Forum" class QueryCreateView(PageTitleMixin, LoginRequiredMixin, generic.CreateView): model = Query template_name = "forum/query_form.html" - fields = ['title', 'content', 'category'] - title = 'Ask' + fields = ["title", "content", "category"] + title = "Ask" def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form) -class QueryUpdateView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView): +class QueryUpdateView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView +): model = Query - fields = ['title', 'content', 'category'] - title = 'Edit Query' + fields = ["title", "content", "category"] + title = "Edit Query" def form_valid(self, form): form.instance.user = self.request.user @@ -69,10 +71,12 @@ def test_func(self): return True -class QueryDeleteView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView): +class QueryDeleteView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView +): model = Query - success_url = reverse_lazy('forum:list') - title = 'Delete Query' + success_url = reverse_lazy("forum:list") + title = "Delete Query" def test_func(self): query = self.get_object() @@ -83,20 +87,22 @@ def test_func(self): class AnswerCreateView(LoginRequiredMixin, PageTitleMixin, generic.CreateView): model = Answer template_name = "forum/answer_form.html" - fields = ['content'] - title = 'Answer' + fields = ["content"] + title = "Answer" def form_valid(self, form): form.instance.user = self.request.user - form.instance.query = Query.objects.get(slug=self.kwargs['qslug']) + form.instance.query = Query.objects.get(slug=self.kwargs["qslug"]) return super().form_valid(form) -class AnswerUpdateView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView): +class AnswerUpdateView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView +): model = Answer template_name = "forum/answer_form.html" - fields = ['content'] - title = 'Edit Answer' + fields = ["content"] + title = "Edit Answer" def form_valid(self, form): form.instance.user = self.request.user @@ -108,10 +114,12 @@ def test_func(self): return True -class AnswerDeleteView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView): +class AnswerDeleteView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView +): model = Answer - success_url = reverse_lazy('forum:list') - title = 'Delete Answer' + success_url = reverse_lazy("forum:list") + title = "Delete Answer" def test_func(self): answer = self.get_object() @@ -119,11 +127,13 @@ def test_func(self): return True -class AcceptAnswerView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView): +class AcceptAnswerView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView +): model = Answer - fields = ['isaccepted'] + fields = ["isaccepted"] template_name = "forum/answer_accept.html" - title = 'Accept Answer' + title = "Accept Answer" def form_valid(self, form): form.instance.user = self.request.user @@ -138,26 +148,28 @@ def test_func(self): class AnswerDetailView(PageTitleMixin, generic.DetailView): model = Answer template_name = "forum/answer_detail.html" - title = 'Answer' + title = "Answer" class CommentCreateView(LoginRequiredMixin, PageTitleMixin, generic.CreateView): model = Comment template_name = "forum/comment_form.html" - fields = ['content'] - title = 'Comment' + fields = ["content"] + title = "Comment" def form_valid(self, form): form.instance.user = self.request.user - form.instance.answer = Answer.objects.get(slug=self.kwargs['aslug']) + form.instance.answer = Answer.objects.get(slug=self.kwargs["aslug"]) return super().form_valid(form) -class CommentUpdateView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView): +class CommentUpdateView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.UpdateView +): model = Comment template_name = "forum/comment_form.html" - fields = ['content'] - title = 'Edit Comment' + fields = ["content"] + title = "Edit Comment" def form_valid(self, form): form.instance.user = self.request.user @@ -169,10 +181,12 @@ def test_func(self): return True -class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView): +class CommentDeleteView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, generic.DeleteView +): model = Comment - success_url = reverse_lazy('forum:list') - title = 'Delete Comment' + success_url = reverse_lazy("forum:list") + title = "Delete Comment" def test_func(self): comment = self.get_object() @@ -182,8 +196,8 @@ def test_func(self): class QueryLikeToggle(generic.RedirectView): def get_redirect_url(self, *args, **kwargs): - query = get_object_or_404(Query, slug=self.kwargs['slug']) - slug = self.kwargs.get('slug') + query = get_object_or_404(Query, slug=self.kwargs["slug"]) + slug = self.kwargs.get("slug") print(slug) obj = get_object_or_404(Query, slug=slug) url_ = obj.get_absolute_url() @@ -197,8 +211,12 @@ def get_redirect_url(self, *args, **kwargs): class QueryLikeAPIToggle(APIView): - authentication_classes = [SessionAuthentication, ] - permission_clases = [IsAuthenticated, ] + authentication_classes = [ + SessionAuthentication, + ] + permission_clases = [ + IsAuthenticated, + ] def get(self, request, slug=None, format=None): obj = get_object_or_404(Query, slug=slug) @@ -214,10 +232,7 @@ def get(self, request, slug=None, format=None): obj.likes.add(user) updated = True - data = { - 'updated': updated, - 'liked': liked - } + data = {"updated": updated, "liked": liked} return Response(data) diff --git a/fusion/apps.py b/fusion/apps.py index de054c7..e48f869 100644 --- a/fusion/apps.py +++ b/fusion/apps.py @@ -2,4 +2,4 @@ class FusionConfig(AppConfig): - name = 'fusion' + name = "fusion" diff --git a/fusion/urls.py b/fusion/urls.py index a689eea..43939e6 100644 --- a/fusion/urls.py +++ b/fusion/urls.py @@ -1,10 +1,9 @@ from django.urls import path -from .views import (FusionHomeView, FusionDetailView - ) -app_name = 'fusion' +from .views import FusionHomeView, FusionDetailView -urlpatterns = [ - path('', FusionHomeView, name='fusion'), - path('immerse/', FusionDetailView, name='fusion-detail'), +app_name = "fusion" +urlpatterns = [ + path("", FusionHomeView, name="fusion"), + path("immerse/", FusionDetailView, name="fusion-detail"), ] diff --git a/fusion/views.py b/fusion/views.py index 717670c..0122046 100644 --- a/fusion/views.py +++ b/fusion/views.py @@ -2,8 +2,8 @@ def FusionHomeView(requests): - return render(requests, "fusion/fusion.html", {'title': 'Fusion'}) + return render(requests, "fusion/fusion.html", {"title": "Fusion"}) def FusionDetailView(requests): - return render(requests, "fusion/fusion_detail.html", {'title': 'Fusion Immerse'}) + return render(requests, "fusion/fusion_detail.html", {"title": "Fusion Immerse"}) diff --git a/manage.py b/manage.py index 4ea9b1c..475b56e 100755 --- a/manage.py +++ b/manage.py @@ -5,7 +5,7 @@ def main(): - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'domecode.settings') + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "domecode.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -17,5 +17,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/notes/admin.py b/notes/admin.py index ec592eb..6d0d0b7 100755 --- a/notes/admin.py +++ b/notes/admin.py @@ -1,8 +1,9 @@ from django.contrib import admin from .models import * + # Register your models here. admin.site.register(Notes) from rest_framework.authtoken.admin import TokenAdmin -TokenAdmin.raw_id_fields = ['user'] +TokenAdmin.raw_id_fields = ["user"] diff --git a/notes/api/serializers.py b/notes/api/serializers.py index 36ad111..b6dda7f 100644 --- a/notes/api/serializers.py +++ b/notes/api/serializers.py @@ -3,6 +3,6 @@ class NotesSerializer(serializers.ModelSerializer): - class Meta: - model = Notes - fields = [ 'user','title','content','category','created'] \ No newline at end of file + class Meta: + model = Notes + fields = ["user", "title", "content", "category", "created"] diff --git a/notes/api/urls.py b/notes/api/urls.py index 464b732..65c6b8f 100644 --- a/notes/api/urls.py +++ b/notes/api/urls.py @@ -1,9 +1,9 @@ from django.urls import path, include from notes.api import views -app_name = 'notes' + +app_name = "notes" urlpatterns = [ - path('', views.NotesList.as_view(), name = 'list' ), - path('/', views.NotesDetail.as_view(), name = 'detail'), + path("", views.NotesList.as_view(), name="list"), + path("/", views.NotesDetail.as_view(), name="detail"), ] - diff --git a/notes/api/views.py b/notes/api/views.py index 06d23ec..a99c2df 100644 --- a/notes/api/views.py +++ b/notes/api/views.py @@ -2,22 +2,25 @@ from notes.api.serializers import NotesSerializer from rest_framework import generics from rest_framework.permissions import IsAdminUser, IsAuthenticated -from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication +from rest_framework.authentication import ( + SessionAuthentication, + BasicAuthentication, + TokenAuthentication, +) from rest_framework.response import Response from rest_framework.views import APIView - class NotesList(generics.ListCreateAPIView): - permission_classes = [IsAdminUser] - queryset = Notes.objects.all() - serializer_class = NotesSerializer + permission_classes = [IsAdminUser] + queryset = Notes.objects.all() + serializer_class = NotesSerializer class NotesDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [IsAdminUser] - queryset = Notes.objects.all() - serializer_class = NotesSerializer + permission_classes = [IsAdminUser] + queryset = Notes.objects.all() + serializer_class = NotesSerializer """ diff --git a/notes/apps.py b/notes/apps.py index b6155ac..a91bbb5 100755 --- a/notes/apps.py +++ b/notes/apps.py @@ -2,4 +2,4 @@ class NotesConfig(AppConfig): - name = 'notes' + name = "notes" diff --git a/notes/migrations/0001_initial.py b/notes/migrations/0001_initial.py index 1cc8efb..beb0cf3 100644 --- a/notes/migrations/0001_initial.py +++ b/notes/migrations/0001_initial.py @@ -16,16 +16,30 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Notes', + name="Notes", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=40)), - ('content', ckeditor.fields.RichTextField(blank=True, null=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('last_modified', models.DateTimeField(auto_now=True)), - ('category', models.CharField(default='CS', max_length=25)), - ('slug', models.SlugField(null=True, unique=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=40)), + ("content", ckeditor.fields.RichTextField(blank=True, null=True)), + ("created", models.DateTimeField(auto_now_add=True)), + ("last_modified", models.DateTimeField(auto_now=True)), + ("category", models.CharField(default="CS", max_length=25)), + ("slug", models.SlugField(null=True, unique=True)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/notes/migrations/0002_auto_20200805_2110.py b/notes/migrations/0002_auto_20200805_2110.py index c6c7d24..d677ca3 100644 --- a/notes/migrations/0002_auto_20200805_2110.py +++ b/notes/migrations/0002_auto_20200805_2110.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('notes', '0001_initial'), + ("notes", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='notes', - name='slug', + model_name="notes", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/notes/models.py b/notes/models.py index 0301f51..ff66f8d 100755 --- a/notes/models.py +++ b/notes/models.py @@ -20,7 +20,7 @@ def __str__(self): return self.title def get_absolute_url(self): - return reverse('notes:detail', kwargs={'slug': self.slug}) + return reverse("notes:detail", kwargs={"slug": self.slug}) def save(self, *args, **kwargs): uniqueid = get_random_string(length=64) diff --git a/notes/templatetags/countit.py b/notes/templatetags/countit.py index e421be9..efec21c 100644 --- a/notes/templatetags/countit.py +++ b/notes/templatetags/countit.py @@ -3,6 +3,7 @@ register = template.Library() + @register.simple_tag def count_posts_of(user): - return Notes.objects.filter(user =user).count() \ No newline at end of file + return Notes.objects.filter(user=user).count() diff --git a/notes/tests.py b/notes/tests.py index 677dff0..98999a2 100755 --- a/notes/tests.py +++ b/notes/tests.py @@ -3,6 +3,7 @@ from django.urls import reverse from .models import Notes from django.contrib.auth.models import User + # Create your tests here. @@ -27,42 +28,42 @@ def test_home_renders_correctly(self): """ Home page should load """ - response = self.client.get(reverse('notes:home')) + response = self.client.get(reverse("notes:home")) self.assertEqual(response.status_code, 200) def test_about_renders_correctly(self): """ About page should load """ - response = self.client.get(reverse('notes:about')) + response = self.client.get(reverse("notes:about")) self.assertEqual(response.status_code, 200) def test_music_renders_correctly(self): """ Music page should load """ - response = self.client.get(reverse('notes:music')) + response = self.client.get(reverse("notes:music")) self.assertEqual(response.status_code, 200) def test_sponsor_renders_correctly(self): """ Sponsor page should load """ - response = self.client.get(reverse('notes:sponsor')) + response = self.client.get(reverse("notes:sponsor")) self.assertEqual(response.status_code, 200) def test_privacy_policy_renders_correctly(self): """ Privacy Policy page should load """ - response = self.client.get(reverse('notes:privacy')) + response = self.client.get(reverse("notes:privacy")) self.assertEqual(response.status_code, 200) def test_tos_renders_correctly(self): """ Terms of Service page should load """ - response = self.client.get(reverse('notes:tos')) + response = self.client.get(reverse("notes:tos")) self.assertEqual(response.status_code, 200) @@ -74,25 +75,29 @@ def test_list_view_works_correctly(self): """ The view must contain the created notes """ - user = create_user(username='TestUser', password='test000') - self.client.login(username='TestUser', password='test000') - create_note(title='TestNote1', user=user) - create_note(title='TestNote2', user=user) - response = self.client.get(reverse('notes:list')) - self.assertContains(response, 'TestNote1') - self.assertContains(response, 'TestNote2') + user = create_user(username="TestUser", password="test000") + self.client.login(username="TestUser", password="test000") + create_note(title="TestNote1", user=user) + create_note(title="TestNote2", user=user) + response = self.client.get(reverse("notes:list")) + self.assertContains(response, "TestNote1") + self.assertContains(response, "TestNote2") def test_list_view_with_search_works_correctly(self): """ The view must return only the queried notes """ - user = create_user(username='TestUser', password='test000') - self.client.post(reverse('login'), {'username': 'TestUser', 'password': 'test000'}) - create_note(title='TestNote1', user=user) - create_note(title='TestNote2', user=user) - response = self.client.get('/notes/?q=TestNote1') # Did not use reverse. This test will fail if url changes - self.assertContains(response, 'TestNote1') - self.assertNotContains(response, 'TestNote2') + user = create_user(username="TestUser", password="test000") + self.client.post( + reverse("login"), {"username": "TestUser", "password": "test000"} + ) + create_note(title="TestNote1", user=user) + create_note(title="TestNote2", user=user) + response = self.client.get( + "/notes/?q=TestNote1" + ) # Did not use reverse. This test will fail if url changes + self.assertContains(response, "TestNote1") + self.assertNotContains(response, "TestNote2") class NotesCreateViewTests(TestCase): @@ -104,19 +109,21 @@ def test_unauthenticated_user_cannot_make_a_note(self): Unauthenticated user shouldn't be able to make a note """ self.client.post( - reverse('notes:create'), - {'title': 'Test Note', 'content': 'Test Content', 'category': 'Test cat'}) + reverse("notes:create"), + {"title": "Test Note", "content": "Test Content", "category": "Test cat"}, + ) self.assertEquals(Notes.objects.all().count(), 0) def test_authenticated_user_can_make_a_note(self): """ Authenticateded user should be able to succesfully make a note """ - create_user(username='TestUser', password='test000') - self.client.login(username='TestUser', password='test000') + create_user(username="TestUser", password="test000") + self.client.login(username="TestUser", password="test000") self.client.post( - reverse('notes:create'), - {'title': 'Test Note', 'content': 'Test Content', 'category': 'Test cat'}) + reverse("notes:create"), + {"title": "Test Note", "content": "Test Content", "category": "Test cat"}, + ) self.assertEquals(Notes.objects.all().count(), 1) @@ -128,21 +135,25 @@ def test_correct_user_can_delete(self): """ Author of the note should be able to delete the note """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user1) # User1 created the note and they will try to delete it - self.client.post(reverse("notes:delete", kwargs={'slug': note.slug})) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user1 + ) # User1 created the note and they will try to delete it + self.client.post(reverse("notes:delete", kwargs={"slug": note.slug})) self.assertEquals(Notes.objects.all().count(), 0) def test_incorrect_user_cannot_delete(self): """ If user is not author of the note they shouldn't be able to delete the note """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user2) # User2 created the note and user1 will try to delete it - self.client.post(reverse("notes:delete", kwargs={'slug': note.slug})) + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user2 + ) # User2 created the note and user1 will try to delete it + self.client.post(reverse("notes:delete", kwargs={"slug": note.slug})) self.assertEquals(Notes.objects.all().count(), 1) @@ -154,21 +165,25 @@ def test_correct_user_can_view(self): """ Author of the note should be able to see the note """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user1) # User1 created the note and they will try to see it - response = self.client.get(reverse("notes:detail", kwargs={'slug': note.slug})) - self.assertContains(response, 'TestNote1') + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user1 + ) # User1 created the note and they will try to see it + response = self.client.get(reverse("notes:detail", kwargs={"slug": note.slug})) + self.assertContains(response, "TestNote1") def test_incorrect_user_cannot_view(self): """ If user is not author of the note they shouldn't be able to view the note """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user2) # User2 created the note and user1 will try to view it - response = self.client.get(reverse("notes:detail", kwargs={'slug': note.slug})) + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user2 + ) # User2 created the note and user1 will try to view it + response = self.client.get(reverse("notes:detail", kwargs={"slug": note.slug})) self.assertEquals(response.status_code, 403) @@ -180,23 +195,29 @@ def test_correct_user_can_update(self): """ Author of the note should be able to succesfully update the note """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user1) # User1 created the note and they will try to update it - self.client.post(reverse( - "notes:update", - kwargs={'slug': note.slug}), {'title': 'Updated_test_note', 'content': 'test_content', 'category': 'CS'}) - self.assertEqual(Notes.objects.all()[0].title, 'Updated_test_note') + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user1 + ) # User1 created the note and they will try to update it + self.client.post( + reverse("notes:update", kwargs={"slug": note.slug}), + {"title": "Updated_test_note", "content": "test_content", "category": "CS"}, + ) + self.assertEqual(Notes.objects.all()[0].title, "Updated_test_note") def test_incorrect_user_cannot_update(self): """ If user is not author of the note they shouldn't be able to view the note """ - create_user(username='TestUser1', password='test000') - user2 = create_user(username='TestUser2', password='test000') - self.client.login(username='TestUser1', password='test000') - note = create_note(title='TestNote1', user=user2) # User2 created the note and user1 will try to update it - self.client.post(reverse( - "notes:update", - kwargs={'slug': note.slug}), {'title': 'Updated_test_note', 'content': 'test_content', 'category': 'CS'}) - self.assertNotEqual(Notes.objects.all()[0].title, 'Updated_test_note') + create_user(username="TestUser1", password="test000") + user2 = create_user(username="TestUser2", password="test000") + self.client.login(username="TestUser1", password="test000") + note = create_note( + title="TestNote1", user=user2 + ) # User2 created the note and user1 will try to update it + self.client.post( + reverse("notes:update", kwargs={"slug": note.slug}), + {"title": "Updated_test_note", "content": "test_content", "category": "CS"}, + ) + self.assertNotEqual(Notes.objects.all()[0].title, "Updated_test_note") diff --git a/notes/urls.py b/notes/urls.py index 031034b..8115ded 100755 --- a/notes/urls.py +++ b/notes/urls.py @@ -1,20 +1,26 @@ # todo - update the urls.py with private and public mode urls from django.urls import path -from .import views -from .views import NotesCreateView, NotesListView, NotesUpdateView, NotesDeleteView, NotesDetailView -app_name = 'notes' +from . import views +from .views import ( + NotesCreateView, + NotesListView, + NotesUpdateView, + NotesDeleteView, + NotesDetailView, +) -urlpatterns = [ - path('', views.home, name='home'), - path('notes/', NotesListView.as_view(), name='list'), - path('notes/new/', NotesCreateView.as_view(), name='create'), - path('notes//delete/', NotesDeleteView.as_view(), name='delete'), - path('notes//', NotesDetailView.as_view(), name='detail'), - path('notes//update/', NotesUpdateView.as_view(), name='update'), - path('about/', views.about, name='about'), - path('music/', views.music, name='music'), - path('sponsor/', views.sponsor, name='sponsor'), - path('privacypolicy/', views.privacy, name='privacy'), - path('termsofservice/', views.tos, name='tos') +app_name = "notes" +urlpatterns = [ + path("", views.home, name="home"), + path("notes/", NotesListView.as_view(), name="list"), + path("notes/new/", NotesCreateView.as_view(), name="create"), + path("notes//delete/", NotesDeleteView.as_view(), name="delete"), + path("notes//", NotesDetailView.as_view(), name="detail"), + path("notes//update/", NotesUpdateView.as_view(), name="update"), + path("about/", views.about, name="about"), + path("music/", views.music, name="music"), + path("sponsor/", views.sponsor, name="sponsor"), + path("privacypolicy/", views.privacy, name="privacy"), + path("termsofservice/", views.tos, name="tos"), ] diff --git a/notes/views.py b/notes/views.py index 260e188..95a35f7 100755 --- a/notes/views.py +++ b/notes/views.py @@ -1,64 +1,73 @@ from django.shortcuts import render from django.urls import reverse_lazy from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin -from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView +from django.views.generic import ( + ListView, + DetailView, + CreateView, + UpdateView, + DeleteView, +) from .models import Notes from django.db.models import Q from domecode.mixins import PageTitleMixin def home(request): - return render(request, 'notes/home.html', {'title': 'Home'}) + return render(request, "notes/home.html", {"title": "Home"}) def about(request): - return render(request, 'notes/about.html', {'title': 'About'}) + return render(request, "notes/about.html", {"title": "About"}) def music(request): - return render(request, 'notes/musicpopup.html', {'title': 'Music'}) + return render(request, "notes/musicpopup.html", {"title": "Music"}) def sponsor(request): - return render(request, "notes/sponsor.html", {'title': 'Sponsor'}) + return render(request, "notes/sponsor.html", {"title": "Sponsor"}) def privacy(request): - return render(request, "notes/privacy.html", {'title': 'Privacy Policy'}) + return render(request, "notes/privacy.html", {"title": "Privacy Policy"}) def tos(request): - return render(request, "notes/termsofservice.html", {'title': 'Terms of Service'}) + return render(request, "notes/termsofservice.html", {"title": "Terms of Service"}) class NotesListView(LoginRequiredMixin, PageTitleMixin, ListView): model = Notes - context_object_name = 'notes' + context_object_name = "notes" title = "Your Notes" paginate_by = 15 def get_queryset(self, *args, **kwargs): object_list = super(NotesListView, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__contains=search, user=self.request.user) | - Q(content__contains=search, user=self.request.user) | - Q(category__contains=search, user=self.request.user) - ).order_by('-last_modified') + Q(title__contains=search, user=self.request.user) + | Q(content__contains=search, user=self.request.user) + | Q(category__contains=search, user=self.request.user) + ).order_by("-last_modified") return object_list else: - object_list = Notes.objects.filter( - user=self.request.user).order_by('-last_modified') + object_list = Notes.objects.filter(user=self.request.user).order_by( + "-last_modified" + ) return object_list -class NotesUpdateView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, UpdateView): +class NotesUpdateView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, UpdateView +): model = Notes - success_url = reverse_lazy('notes:list') + success_url = reverse_lazy("notes:list") title = "Update Note" - fields = ['title', 'content', 'category'] + fields = ["title", "content", "category"] def form_valid(self, form): form.instance.user = self.request.user @@ -70,9 +79,11 @@ def test_func(self): return True -class NotesDetailView(PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, DetailView): +class NotesDetailView( + PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, DetailView +): model = Notes - title = 'Notes' + title = "Notes" def test_func(self): notes = self.get_object() @@ -80,9 +91,11 @@ def test_func(self): return True -class NotesDeleteView(LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, DeleteView): +class NotesDeleteView( + LoginRequiredMixin, UserPassesTestMixin, PageTitleMixin, DeleteView +): model = Notes - success_url = reverse_lazy('notes:list') + success_url = reverse_lazy("notes:list") title = "Delete Note" def test_func(self): @@ -93,9 +106,9 @@ def test_func(self): class NotesCreateView(LoginRequiredMixin, PageTitleMixin, CreateView): model = Notes - fields = ['title', 'content', 'category'] + fields = ["title", "content", "category"] title = "Create Note" - success_url = reverse_lazy('notes:list') + success_url = reverse_lazy("notes:list") def form_valid(self, form): form.instance.user = self.request.user diff --git a/quizzes/apps.py b/quizzes/apps.py index f55d094..9864f76 100644 --- a/quizzes/apps.py +++ b/quizzes/apps.py @@ -2,4 +2,4 @@ class QuizzesConfig(AppConfig): - name = 'quizzes' + name = "quizzes" diff --git a/quizzes/forms.py b/quizzes/forms.py index 82288cf..fd96ee4 100644 --- a/quizzes/forms.py +++ b/quizzes/forms.py @@ -5,4 +5,4 @@ class ResultForm(forms.ModelForm): class Meta: model = Answer - fields = ['answer'] + fields = ["answer"] diff --git a/quizzes/migrations/0001_initial.py b/quizzes/migrations/0001_initial.py index a5afaa4..b824885 100644 --- a/quizzes/migrations/0001_initial.py +++ b/quizzes/migrations/0001_initial.py @@ -16,33 +16,116 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Quiz', + name="Quiz", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('typeof', models.CharField(choices=[('EASY', 'Easy Difficulty'), ('MEDIUM', 'Medium Difficulty'), ('HARD', 'Hard Difficulty')], default='EASY', max_length=6, null=True)), - ('Language', models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=10)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ( + "typeof", + models.CharField( + choices=[ + ("EASY", "Easy Difficulty"), + ("MEDIUM", "Medium Difficulty"), + ("HARD", "Hard Difficulty"), + ], + default="EASY", + max_length=6, + null=True, + ), + ), + ( + "Language", + models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), + ), ], ), migrations.CreateModel( - name='Ques', + name="Ques", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('content', ckeditor.fields.RichTextField()), - ('solution', models.CharField(choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')], default='A', max_length=1)), - ('slug', models.SlugField(null=True, unique=True)), - ('quiz', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='quizzes.Quiz')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=100)), + ("content", ckeditor.fields.RichTextField()), + ( + "solution", + models.CharField( + choices=[("A", "A"), ("B", "B"), ("C", "C"), ("D", "D")], + default="A", + max_length=1, + ), + ), + ("slug", models.SlugField(null=True, unique=True)), + ( + "quiz", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="quizzes.Quiz", + ), + ), ], ), migrations.CreateModel( - name='Answer', + name="Answer", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('iscorrect', models.BooleanField(default=False)), - ('answer', models.CharField(choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')], default='A', max_length=1)), - ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quizzes.Ques')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quizuser', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("iscorrect", models.BooleanField(default=False)), + ( + "answer", + models.CharField( + choices=[("A", "A"), ("B", "B"), ("C", "C"), ("D", "D")], + default="A", + max_length=1, + ), + ), + ( + "question", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="quizzes.Ques" + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="quizuser", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/quizzes/migrations/0002_quiz_slug.py b/quizzes/migrations/0002_quiz_slug.py index 1dd8c1e..544ef0f 100644 --- a/quizzes/migrations/0002_quiz_slug.py +++ b/quizzes/migrations/0002_quiz_slug.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0001_initial'), + ("quizzes", "0001_initial"), ] operations = [ migrations.AddField( - model_name='quiz', - name='slug', + model_name="quiz", + name="slug", field=models.SlugField(null=True, unique=True), ), ] diff --git a/quizzes/migrations/0003_ques_language.py b/quizzes/migrations/0003_ques_language.py index dfd5091..c369537 100644 --- a/quizzes/migrations/0003_ques_language.py +++ b/quizzes/migrations/0003_ques_language.py @@ -6,13 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0002_quiz_slug'), + ("quizzes", "0002_quiz_slug"), ] operations = [ migrations.AddField( - model_name='ques', - name='Language', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=7), + model_name="ques", + name="Language", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=7, + ), ), ] diff --git a/quizzes/migrations/0004_auto_20200801_0749.py b/quizzes/migrations/0004_auto_20200801_0749.py index c6d43f4..31df1be 100644 --- a/quizzes/migrations/0004_auto_20200801_0749.py +++ b/quizzes/migrations/0004_auto_20200801_0749.py @@ -6,13 +6,24 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0003_ques_language'), + ("quizzes", "0003_ques_language"), ] operations = [ migrations.AlterField( - model_name='ques', - name='Language', - field=models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=7, null=True), + model_name="ques", + name="Language", + field=models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=7, + null=True, + ), ), ] diff --git a/quizzes/migrations/0005_auto_20200802_1650.py b/quizzes/migrations/0005_auto_20200802_1650.py index 4caccac..30f4e21 100644 --- a/quizzes/migrations/0005_auto_20200802_1650.py +++ b/quizzes/migrations/0005_auto_20200802_1650.py @@ -6,13 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0004_auto_20200801_0749'), + ("quizzes", "0004_auto_20200801_0749"), ] operations = [ migrations.AlterField( - model_name='quiz', - name='Language', - field=models.CharField(choices=[('java', 'Java'), ('python', 'Python'), ('rust', 'Rust'), ('c++', 'C++'), ('general', 'General')], default='PYTHON', max_length=10), + model_name="quiz", + name="Language", + field=models.CharField( + choices=[ + ("java", "Java"), + ("python", "Python"), + ("rust", "Rust"), + ("c++", "C++"), + ("general", "General"), + ], + default="PYTHON", + max_length=10, + ), ), ] diff --git a/quizzes/migrations/0006_auto_20200802_1652.py b/quizzes/migrations/0006_auto_20200802_1652.py index 20856b5..14766fa 100644 --- a/quizzes/migrations/0006_auto_20200802_1652.py +++ b/quizzes/migrations/0006_auto_20200802_1652.py @@ -6,13 +6,23 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0005_auto_20200802_1650'), + ("quizzes", "0005_auto_20200802_1650"), ] operations = [ migrations.AlterField( - model_name='quiz', - name='Language', - field=models.CharField(choices=[('java', 'Java'), ('python', 'Python'), ('rust', 'Rust'), ('c++', 'C++'), ('general', 'General')], default='python', max_length=10), + model_name="quiz", + name="Language", + field=models.CharField( + choices=[ + ("java", "Java"), + ("python", "Python"), + ("rust", "Rust"), + ("c++", "C++"), + ("general", "General"), + ], + default="python", + max_length=10, + ), ), ] diff --git a/quizzes/migrations/0007_auto_20200805_2110.py b/quizzes/migrations/0007_auto_20200805_2110.py index 3c20362..ef8e506 100644 --- a/quizzes/migrations/0007_auto_20200805_2110.py +++ b/quizzes/migrations/0007_auto_20200805_2110.py @@ -6,18 +6,18 @@ class Migration(migrations.Migration): dependencies = [ - ('quizzes', '0006_auto_20200802_1652'), + ("quizzes", "0006_auto_20200802_1652"), ] operations = [ migrations.AlterField( - model_name='ques', - name='slug', + model_name="ques", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), migrations.AlterField( - model_name='quiz', - name='slug', + model_name="quiz", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/quizzes/models.py b/quizzes/models.py index 9468eec..25e0cd7 100644 --- a/quizzes/models.py +++ b/quizzes/models.py @@ -6,22 +6,20 @@ class Quiz(models.Model): CATEGORY = [ - ('EASY', 'Easy Difficulty'), - ('MEDIUM', 'Medium Difficulty'), - ('HARD', 'Hard Difficulty'), + ("EASY", "Easy Difficulty"), + ("MEDIUM", "Medium Difficulty"), + ("HARD", "Hard Difficulty"), ] Language = [ - ('java', 'Java'), - ('python', 'Python'), - ('rust', 'Rust'), - ('c++', 'C++'), - ('general', 'General') + ("java", "Java"), + ("python", "Python"), + ("rust", "Rust"), + ("c++", "C++"), + ("general", "General"), ] name = models.CharField(max_length=100) - typeof = models.CharField( - max_length=6, choices=CATEGORY, default='EASY', null=True) - Language = models.CharField( - max_length=10, choices=Language, default='python') + typeof = models.CharField(max_length=6, choices=CATEGORY, default="EASY", null=True) + Language = models.CharField(max_length=10, choices=Language, default="python") slug = models.SlugField(null=True, unique=True, max_length=256) def save(self, *args, **kwargs): @@ -31,25 +29,21 @@ def save(self, *args, **kwargs): class Ques(models.Model): - Choices = [ - ('A', 'A'), - ('B', 'B'), - ('C', 'C'), - ('D', 'D') - ] + Choices = [("A", "A"), ("B", "B"), ("C", "C"), ("D", "D")] Language = [ - ('JAVA', 'Java'), - ('PYTHON', 'Python'), - ('RUST', 'Rust'), - ('C++', 'C++'), - ('General', 'General') + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), ] quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, null=True) title = models.CharField(max_length=100) content = RichTextField() Language = models.CharField( - max_length=7, choices=Language, default='PYTHON', null=True) - solution = models.CharField(max_length=1, choices=Choices, default='A') + max_length=7, choices=Language, default="PYTHON", null=True + ) + solution = models.CharField(max_length=1, choices=Choices, default="A") slug = models.SlugField(null=True, unique=True, max_length=256) def __str__(self): @@ -61,14 +55,10 @@ def save(self, *args, **kwargs): class Answer(models.Model): - Choices = [ - ('A', 'A'), - ('B', 'B'), - ('C', 'C'), - ('D', 'D') - ] - user = models.ForeignKey(get_user_model(), null=True, - on_delete=models.SET_NULL, related_name="quizuser") + Choices = [("A", "A"), ("B", "B"), ("C", "C"), ("D", "D")] + user = models.ForeignKey( + get_user_model(), null=True, on_delete=models.SET_NULL, related_name="quizuser" + ) question = models.ForeignKey(Ques, on_delete=models.CASCADE) iscorrect = models.BooleanField(default=False) - answer = models.CharField(max_length=1, choices=Choices, default='A') + answer = models.CharField(max_length=1, choices=Choices, default="A") diff --git a/quizzes/tests.py b/quizzes/tests.py index 77576a9..2eea463 100644 --- a/quizzes/tests.py +++ b/quizzes/tests.py @@ -3,16 +3,17 @@ from django.urls import reverse from .models import Quiz, Ques, Answer from django.contrib.auth.models import User + # Create your tests here. -def create_quiz(name, Language='python', typeof='EASY'): +def create_quiz(name, Language="python", typeof="EASY"): quiz = Quiz(name=name, Language=Language, typeof=typeof) quiz.save() return quiz -def create_ques(title, quiz, solution='A'): +def create_ques(title, quiz, solution="A"): ques = Ques(title=title, quiz=quiz, solution=solution) ques.save() return ques @@ -33,9 +34,9 @@ def test_home_renders_correctly(self): """ Home page should load """ - create_quiz('TestQuiz') - response = self.client.get(reverse('quizzes:home')) - self.assertContains(response, 'TestQuiz') + create_quiz("TestQuiz") + response = self.client.get(reverse("quizzes:home")) + self.assertContains(response, "TestQuiz") class QuizDetailsViewTests(TestCase): @@ -46,15 +47,17 @@ def test_list_view_works_correctly(self): """ The view must contain the ques in the created quiz and none of the questions of other quizzes """ - quiz1 = create_quiz('TestQuiz1') - quiz2 = create_quiz('TestQuiz2') - create_ques(title='TestQues1', quiz=quiz1) - create_ques(title='TestQues2', quiz=quiz1) - create_ques(title='TestQues3', quiz=quiz2) - response = self.client.get(reverse('quizzes:detail-python', kwargs={'slug': quiz1.slug})) - self.assertContains(response, 'TestQues1') - self.assertContains(response, 'TestQues2') - self.assertNotContains(response, 'TestQues3') + quiz1 = create_quiz("TestQuiz1") + quiz2 = create_quiz("TestQuiz2") + create_ques(title="TestQues1", quiz=quiz1) + create_ques(title="TestQues2", quiz=quiz1) + create_ques(title="TestQues3", quiz=quiz2) + response = self.client.get( + reverse("quizzes:detail-python", kwargs={"slug": quiz1.slug}) + ) + self.assertContains(response, "TestQues1") + self.assertContains(response, "TestQues2") + self.assertNotContains(response, "TestQues3") class QuesDetailsViewTesst(TestCase): @@ -65,21 +68,25 @@ def test_unauthenticated_user_cannot_view_ques(self): """ Unauthenticated user shouldn't be able to view """ - quiz = create_quiz('TestQuiz') - ques = create_ques(title='TestQues', quiz=quiz) - response = self.client.get(reverse('quizzes:detail', kwargs={'slug': ques.slug}), follow=True) - self.assertNotContains(response, 'TestQues') + quiz = create_quiz("TestQuiz") + ques = create_ques(title="TestQues", quiz=quiz) + response = self.client.get( + reverse("quizzes:detail", kwargs={"slug": ques.slug}), follow=True + ) + self.assertNotContains(response, "TestQues") def test_authenticated_user_can_view_the_ques(self): """ Ques should render correctly for authed user. """ - create_user(username='TestUser', password='test000') - self.client.login(username='TestUser', password='test000') - quiz = create_quiz('TestQuiz') - ques = create_ques(title='TestQues', quiz=quiz) - response = self.client.get(reverse('quizzes:detail', kwargs={'slug': ques.slug})) - self.assertContains(response, 'TestQues') + create_user(username="TestUser", password="test000") + self.client.login(username="TestUser", password="test000") + quiz = create_quiz("TestQuiz") + ques = create_ques(title="TestQues", quiz=quiz) + response = self.client.get( + reverse("quizzes:detail", kwargs={"slug": ques.slug}) + ) + self.assertContains(response, "TestQues") class AnswerCreateViewTests(TestCase): @@ -90,38 +97,74 @@ def test_answer_create_view_works_correctly_easy(self): """ On creating an answer the domes of the user must update correctly for easy quiz """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - quiz = create_quiz('TestQuiz') - ques1 = create_ques(title='TestQues1', quiz=quiz, solution='B') - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'A'}) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + quiz = create_quiz("TestQuiz") + ques1 = create_ques(title="TestQues1", quiz=quiz, solution="B") + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "A"}, + ) user1.refresh_from_db() - self.assertEquals(Answer.objects.filter(question=ques1).filter(user=user1).filter(iscorrect=True).count(), 0) + self.assertEquals( + Answer.objects.filter(question=ques1) + .filter(user=user1) + .filter(iscorrect=True) + .count(), + 0, + ) self.assertEquals(user1.profile.domes, 0) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() - self.assertEquals(Answer.objects.filter(question=ques1).filter(user=user1).filter(iscorrect=True).count(), 1) + self.assertEquals( + Answer.objects.filter(question=ques1) + .filter(user=user1) + .filter(iscorrect=True) + .count(), + 1, + ) self.assertEquals(user1.profile.domes, 2) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() - self.assertEquals(Answer.objects.filter(question=ques1).filter(user=user1).filter(iscorrect=True).count(), 2) + self.assertEquals( + Answer.objects.filter(question=ques1) + .filter(user=user1) + .filter(iscorrect=True) + .count(), + 2, + ) self.assertEquals(user1.profile.domes, 2) def test_answer_create_view_works_correctly_medium(self): """ On creating an answer the domes of the user must update correctly for easy quiz """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - quiz = create_quiz('TestQuiz', typeof='MEDIUM') - ques1 = create_ques(title='TestQues1', quiz=quiz, solution='B') - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'A'}) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + quiz = create_quiz("TestQuiz", typeof="MEDIUM") + ques1 = create_ques(title="TestQues1", quiz=quiz, solution="B") + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "A"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 0) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 4) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 4) @@ -129,17 +172,26 @@ def test_answer_create_view_works_correctly_hard(self): """ On creating an answer the domes of the user must update correctly for easy quiz """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - quiz = create_quiz('TestQuiz', typeof='HARD') - ques1 = create_ques(title='TestQues1', quiz=quiz, solution='B') - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'A'}) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + quiz = create_quiz("TestQuiz", typeof="HARD") + ques1 = create_ques(title="TestQues1", quiz=quiz, solution="B") + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "A"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 0) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 10) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() self.assertEquals(user1.profile.domes, 10) @@ -147,16 +199,34 @@ def test_answer_create_view_for_multiple_ques_works_correctly(self): """ On creating an answer the domes of the user must update correctly for easy quiz """ - user1 = create_user(username='TestUser1', password='test000') - self.client.login(username='TestUser1', password='test000') - quiz = create_quiz('TestQuiz') - ques1 = create_ques(title='TestQues1', quiz=quiz, solution='B') - ques2 = create_ques(title='TestQues2', quiz=quiz, solution='B') - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques1.slug}), data={'answer': 'B'}) + user1 = create_user(username="TestUser1", password="test000") + self.client.login(username="TestUser1", password="test000") + quiz = create_quiz("TestQuiz") + ques1 = create_ques(title="TestQues1", quiz=quiz, solution="B") + ques2 = create_ques(title="TestQues2", quiz=quiz, solution="B") + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques1.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() - self.assertEquals(Answer.objects.filter(question=ques1).filter(user=user1).filter(iscorrect=True).count(), 1) + self.assertEquals( + Answer.objects.filter(question=ques1) + .filter(user=user1) + .filter(iscorrect=True) + .count(), + 1, + ) self.assertEquals(user1.profile.domes, 2) - self.client.post(reverse("quizzes:submit", kwargs={'qslug': ques2.slug}), data={'answer': 'B'}) + self.client.post( + reverse("quizzes:submit", kwargs={"qslug": ques2.slug}), + data={"answer": "B"}, + ) user1.refresh_from_db() - self.assertEquals(Answer.objects.filter(question=ques2).filter(user=user1).filter(iscorrect=True).count(), 1) + self.assertEquals( + Answer.objects.filter(question=ques2) + .filter(user=user1) + .filter(iscorrect=True) + .count(), + 1, + ) self.assertEquals(user1.profile.domes, 4) diff --git a/quizzes/urls.py b/quizzes/urls.py index d164101..49a8bce 100644 --- a/quizzes/urls.py +++ b/quizzes/urls.py @@ -1,10 +1,11 @@ from django.urls import path from .views import AnswerCreateView, QuesDetailView, QuizDetailView, QuizHomeView -app_name = 'quizzes' + +app_name = "quizzes" urlpatterns = [ - path('', QuizHomeView.as_view(), name='home'), - path('python/', QuizDetailView.as_view(), name='detail-python'), - path('question/', QuesDetailView.as_view(), name='detail'), - path('/answer/', AnswerCreateView.as_view(), name='submit') + path("", QuizHomeView.as_view(), name="home"), + path("python/", QuizDetailView.as_view(), name="detail-python"), + path("question/", QuesDetailView.as_view(), name="detail"), + path("/answer/", AnswerCreateView.as_view(), name="submit"), ] diff --git a/quizzes/views.py b/quizzes/views.py index cf26309..7a3529e 100644 --- a/quizzes/views.py +++ b/quizzes/views.py @@ -9,7 +9,7 @@ class QuizHomeView(PageTitleMixin, ListView): model = Quiz template_name = "quizzes/quiz_home.html" context_object_name = "quiz" - title = 'Quizzes' + title = "Quizzes" """ @@ -36,41 +36,48 @@ class QuizDetailView(PageTitleMixin, DetailView): model = Quiz template_name = "quizzes/quiz_detail.html" context_object_name = "ques" - title = 'Quizzes - List' + title = "Quizzes - List" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) instance = self.get_object() - context['ques'] = instance.ques_set.all() + context["ques"] = instance.ques_set.all() return context # TODO: Can remove LoginRequiredMixin class QuesDetailView(PageTitleMixin, LoginRequiredMixin, DetailView): model = Ques - title = 'Quiz Question' + title = "Quiz Question" template_name = "quizzes/ques_detail.html" class AnswerCreateView(PageTitleMixin, LoginRequiredMixin, CreateView): model = Answer - title = 'Attempt Question' - fields = ['answer'] + title = "Attempt Question" + fields = ["answer"] def get_success_url(self): question = self.object.question - return reverse('quizzes:detail', kwargs={'slug': question.slug}) + return reverse("quizzes:detail", kwargs={"slug": question.slug}) def form_valid(self, form): form.instance.user = self.request.user - question = Ques.objects.get(slug=self.kwargs['qslug']) + question = Ques.objects.get(slug=self.kwargs["qslug"]) form.instance.question = question if form.instance.answer == question.solution: form.instance.iscorrect = True - if form.instance.iscorrect and Answer.objects.filter(question=question).filter(user=form.instance.user).filter(iscorrect=True).count() == 0: + if ( + form.instance.iscorrect + and Answer.objects.filter(question=question) + .filter(user=form.instance.user) + .filter(iscorrect=True) + .count() + == 0 + ): if form.instance.question.quiz.typeof == "EASY": form.instance.user.profile.domes += 2 if form.instance.question.quiz.typeof == "MEDIUM": diff --git a/resources/apps.py b/resources/apps.py index f2155dc..cbf046b 100644 --- a/resources/apps.py +++ b/resources/apps.py @@ -2,4 +2,4 @@ class ResourcesConfig(AppConfig): - name = 'resources' + name = "resources" diff --git a/resources/migrations/0001_initial.py b/resources/migrations/0001_initial.py index 485cd4b..b9d0e6f 100644 --- a/resources/migrations/0001_initial.py +++ b/resources/migrations/0001_initial.py @@ -8,20 +8,40 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Resource', + name="Resource", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('content', ckeditor.fields.RichTextField()), - ('category', models.CharField(max_length=300)), - ('language', models.CharField(choices=[('JAVA', 'Java'), ('PYTHON', 'Python'), ('RUST', 'Rust'), ('C++', 'C++'), ('General', 'General')], default='PYTHON', max_length=10)), - ('slug', models.SlugField(null=True, unique=True)), - ('quizlink', models.CharField(max_length=100)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=100)), + ("content", ckeditor.fields.RichTextField()), + ("category", models.CharField(max_length=300)), + ( + "language", + models.CharField( + choices=[ + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), + ], + default="PYTHON", + max_length=10, + ), + ), + ("slug", models.SlugField(null=True, unique=True)), + ("quizlink", models.CharField(max_length=100)), ], ), ] diff --git a/resources/migrations/0002_resource_serialno.py b/resources/migrations/0002_resource_serialno.py index 0dcffba..72027d7 100644 --- a/resources/migrations/0002_resource_serialno.py +++ b/resources/migrations/0002_resource_serialno.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0001_initial'), + ("resources", "0001_initial"), ] operations = [ migrations.AddField( - model_name='resource', - name='serialno', + model_name="resource", + name="serialno", field=models.IntegerField(blank=True, null=True), ), ] diff --git a/resources/migrations/0003_auto_20200727_0345.py b/resources/migrations/0003_auto_20200727_0345.py index dba8e92..7fa1f51 100644 --- a/resources/migrations/0003_auto_20200727_0345.py +++ b/resources/migrations/0003_auto_20200727_0345.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0002_resource_serialno'), + ("resources", "0002_resource_serialno"), ] operations = [ migrations.AlterField( - model_name='resource', - name='quizlink', + model_name="resource", + name="quizlink", field=models.CharField(max_length=100, null=True), ), ] diff --git a/resources/migrations/0004_auto_20200727_2300.py b/resources/migrations/0004_auto_20200727_2300.py index b9649ca..6663e41 100644 --- a/resources/migrations/0004_auto_20200727_2300.py +++ b/resources/migrations/0004_auto_20200727_2300.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0003_auto_20200727_0345'), + ("resources", "0003_auto_20200727_0345"), ] operations = [ migrations.AlterField( - model_name='resource', - name='quizlink', + model_name="resource", + name="quizlink", field=models.CharField(blank=True, max_length=100, null=True), ), ] diff --git a/resources/migrations/0005_auto_20200805_2110.py b/resources/migrations/0005_auto_20200805_2110.py index 07b7d07..8ce1edd 100644 --- a/resources/migrations/0005_auto_20200805_2110.py +++ b/resources/migrations/0005_auto_20200805_2110.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0004_auto_20200727_2300'), + ("resources", "0004_auto_20200727_2300"), ] operations = [ migrations.AlterField( - model_name='resource', - name='slug', + model_name="resource", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/resources/migrations/0006_resource_isdone.py b/resources/migrations/0006_resource_isdone.py index 848e05d..7ee8040 100644 --- a/resources/migrations/0006_resource_isdone.py +++ b/resources/migrations/0006_resource_isdone.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0005_auto_20200805_2110'), + ("resources", "0005_auto_20200805_2110"), ] operations = [ migrations.AddField( - model_name='resource', - name='isdone', + model_name="resource", + name="isdone", field=models.BooleanField(default=False), ), ] diff --git a/resources/migrations/0007_remove_resource_isdone.py b/resources/migrations/0007_remove_resource_isdone.py index a94a503..5fd5f38 100644 --- a/resources/migrations/0007_remove_resource_isdone.py +++ b/resources/migrations/0007_remove_resource_isdone.py @@ -6,12 +6,12 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0006_resource_isdone'), + ("resources", "0006_resource_isdone"), ] operations = [ migrations.RemoveField( - model_name='resource', - name='isdone', + model_name="resource", + name="isdone", ), ] diff --git a/resources/migrations/0008_resource_isdone.py b/resources/migrations/0008_resource_isdone.py index 10e22ec..a292346 100644 --- a/resources/migrations/0008_resource_isdone.py +++ b/resources/migrations/0008_resource_isdone.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0007_remove_resource_isdone'), + ("resources", "0007_remove_resource_isdone"), ] operations = [ migrations.AddField( - model_name='resource', - name='isdone', + model_name="resource", + name="isdone", field=models.BooleanField(default=False), ), ] diff --git a/resources/migrations/0009_auto_20200809_2224.py b/resources/migrations/0009_auto_20200809_2224.py index ef8f1c7..d5aa420 100644 --- a/resources/migrations/0009_auto_20200809_2224.py +++ b/resources/migrations/0009_auto_20200809_2224.py @@ -9,21 +9,42 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('resources', '0008_resource_isdone'), + ("resources", "0008_resource_isdone"), ] operations = [ migrations.RemoveField( - model_name='resource', - name='isdone', + model_name="resource", + name="isdone", ), migrations.CreateModel( - name='Progress', + name="Progress", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('isdone', models.BooleanField(default=False)), - ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='resources.resource')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("isdone", models.BooleanField(default=False)), + ( + "resource", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="resources.resource", + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/resources/migrations/0010_progress_slug.py b/resources/migrations/0010_progress_slug.py index 52ccdb5..c2978f3 100644 --- a/resources/migrations/0010_progress_slug.py +++ b/resources/migrations/0010_progress_slug.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('resources', '0009_auto_20200809_2224'), + ("resources", "0009_auto_20200809_2224"), ] operations = [ migrations.AddField( - model_name='progress', - name='slug', + model_name="progress", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/resources/models.py b/resources/models.py index dba1a86..a34c8e7 100644 --- a/resources/models.py +++ b/resources/models.py @@ -10,18 +10,17 @@ class Resource(models.Model): LANGUAGE = [ - ('JAVA', 'Java'), - ('PYTHON', 'Python'), - ('RUST', 'Rust'), - ('C++', 'C++'), - ('General', 'General') + ("JAVA", "Java"), + ("PYTHON", "Python"), + ("RUST", "Rust"), + ("C++", "C++"), + ("General", "General"), ] title = models.CharField(max_length=100) serialno = models.IntegerField(null=True, blank=True) content = RichTextField() category = models.CharField(max_length=300) - language = models.CharField( - max_length=10, choices=LANGUAGE, default='PYTHON') + language = models.CharField(max_length=10, choices=LANGUAGE, default="PYTHON") slug = models.SlugField(null=True, unique=True, max_length=256) quizlink = models.CharField(max_length=100, null=True, blank=True) @@ -33,13 +32,12 @@ def save(self, *args, **kwargs): super().save(*args, **kwargs) def get_absolute_url(self): - return reverse('resource:detail-python', kwargs={'slug': self.slug}) + return reverse("resource:detail-python", kwargs={"slug": self.slug}) class Progress(models.Model): resource = models.ForeignKey(Resource, on_delete=models.CASCADE) - user = models.ForeignKey( - get_user_model(), null=True, on_delete=models.SET_NULL) + user = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL) isdone = models.BooleanField(default=False) slug = models.SlugField(null=True, unique=True, max_length=256) diff --git a/resources/urls.py b/resources/urls.py index 2b768b7..e8bf318 100644 --- a/resources/urls.py +++ b/resources/urls.py @@ -1,10 +1,11 @@ from django.urls import path -from .import views +from . import views from .views import ResourceDetailViewPy, ResourceDetailViewJava, ResourcesHome -app_name = 'resources' + +app_name = "resources" urlpatterns = [ - path('', ResourcesHome.as_view(), name='home'), - path('python//', ResourceDetailViewPy.as_view(), name='detail-python'), - path('java//', ResourceDetailViewJava.as_view(), name='detail-java'), + path("", ResourcesHome.as_view(), name="home"), + path("python//", ResourceDetailViewPy.as_view(), name="detail-python"), + path("java//", ResourceDetailViewJava.as_view(), name="detail-java"), ] diff --git a/resources/views.py b/resources/views.py index b6c1f01..e5342ce 100644 --- a/resources/views.py +++ b/resources/views.py @@ -1,4 +1,4 @@ -from django.views.generic import ListView, DetailView, CreateView,UpdateView +from django.views.generic import ListView, DetailView, CreateView, UpdateView from domecode.mixins import PageTitleMixin from .models import Progress, Resource from django.urls import reverse_lazy @@ -19,13 +19,11 @@ class ResourceDetailViewPy(PageTitleMixin, DetailView): def get_context_data(self, **kwargs): context = super(ResourceDetailViewPy, self).get_context_data(**kwargs) - context['resources'] = Resource.objects.filter( - language="PYTHON") + context["resources"] = Resource.objects.filter(language="PYTHON") return context def get_queryset(self, *args, **kwargs): - object_list = Resource.objects.filter( - language="PYTHON") + object_list = Resource.objects.filter(language="PYTHON") return object_list @@ -35,13 +33,10 @@ class ResourceDetailViewJava(PageTitleMixin, DetailView): template_name = "resources/resources_detail_java.html" def get_context_data(self, **kwargs): - context = super(ResourceDetailViewJava, - self).get_context_data(**kwargs) - context['resources'] = Resource.objects.filter( - language="JAVA") + context = super(ResourceDetailViewJava, self).get_context_data(**kwargs) + context["resources"] = Resource.objects.filter(language="JAVA") return context def get_queryset(self, *args, **kwargs): - object_list = Resource.objects.filter( - language="JAVA") + object_list = Resource.objects.filter(language="JAVA") return object_list diff --git a/todo/admin.py b/todo/admin.py index 8a93453..fddbf67 100644 --- a/todo/admin.py +++ b/todo/admin.py @@ -4,4 +4,4 @@ admin.site.register(Todo) from rest_framework.authtoken.admin import TokenAdmin -TokenAdmin.raw_id_fields = ['user'] +TokenAdmin.raw_id_fields = ["user"] diff --git a/todo/api/serializers.py b/todo/api/serializers.py index 49cd238..acbb6ed 100644 --- a/todo/api/serializers.py +++ b/todo/api/serializers.py @@ -3,6 +3,6 @@ class TodoSerializer(serializers.ModelSerializer): - class Meta: - model = Todo - fields = [ 'user','title','content','created'] \ No newline at end of file + class Meta: + model = Todo + fields = ["user", "title", "content", "created"] diff --git a/todo/api/urls.py b/todo/api/urls.py index cee2687..1913717 100644 --- a/todo/api/urls.py +++ b/todo/api/urls.py @@ -2,10 +2,10 @@ from rest_framework.urlpatterns import format_suffix_patterns from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope from todo.api import views -app_name = 'todo' + +app_name = "todo" urlpatterns = [ - path('', views.TodoList.as_view(), name = 'list' ), - path('/', views.TodoDetail.as_view(), name = 'detail'), + path("", views.TodoList.as_view(), name="list"), + path("/", views.TodoDetail.as_view(), name="detail"), ] - diff --git a/todo/api/views.py b/todo/api/views.py index dc6c3f9..bd6577c 100644 --- a/todo/api/views.py +++ b/todo/api/views.py @@ -4,14 +4,15 @@ from rest_framework.response import Response from rest_framework.views import APIView + class TodoList(generics.ListCreateAPIView): - queryset = Todo.objects.all() - serializer_class = TodoSerializer + queryset = Todo.objects.all() + serializer_class = TodoSerializer class TodoDetail(generics.RetrieveUpdateDestroyAPIView): - queryset = Todo.objects.all() - serializer_class = TodoSerializer + queryset = Todo.objects.all() + serializer_class = TodoSerializer """ diff --git a/todo/apps.py b/todo/apps.py index 2102482..b4f06d5 100644 --- a/todo/apps.py +++ b/todo/apps.py @@ -2,4 +2,4 @@ class TodoConfig(AppConfig): - name = 'todo' + name = "todo" diff --git a/todo/migrations/0001_initial.py b/todo/migrations/0001_initial.py index cd132bb..35bff47 100644 --- a/todo/migrations/0001_initial.py +++ b/todo/migrations/0001_initial.py @@ -15,13 +15,27 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Todo', + name="Todo", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=30)), - ('content', models.CharField(blank=True, max_length=450)), - ('created', models.DateTimeField(auto_now_add=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=30)), + ("content", models.CharField(blank=True, max_length=450)), + ("created", models.DateTimeField(auto_now_add=True)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/todo/models.py b/todo/models.py index 1238405..6b65ade 100644 --- a/todo/models.py +++ b/todo/models.py @@ -2,14 +2,15 @@ from django.urls import reverse from django.contrib.auth.models import User + class Todo(models.Model): - title = models.CharField(max_length=30) - user = models.ForeignKey(User, on_delete=models.CASCADE) - content= models.CharField(max_length=450,blank=True) - created = models.DateTimeField(auto_now_add=True) + title = models.CharField(max_length=30) + user = models.ForeignKey(User, on_delete=models.CASCADE) + content = models.CharField(max_length=450, blank=True) + created = models.DateTimeField(auto_now_add=True) - def __str__(self): - return self.title + def __str__(self): + return self.title - def get_absolute_url(self): - return reverse('todo:detail', kwargs={'pk': self.pk}) + def get_absolute_url(self): + return reverse("todo:detail", kwargs={"pk": self.pk}) diff --git a/todo/templatetags/countodo.py b/todo/templatetags/countodo.py index e5aed74..99e652e 100644 --- a/todo/templatetags/countodo.py +++ b/todo/templatetags/countodo.py @@ -3,6 +3,7 @@ register = template.Library() + @register.simple_tag def count_posts_of(user): - return Todo.objects.filter(user =user).count() \ No newline at end of file + return Todo.objects.filter(user=user).count() diff --git a/todo/tests/test_models.py b/todo/tests/test_models.py index a02da4e..e419855 100644 --- a/todo/tests/test_models.py +++ b/todo/tests/test_models.py @@ -3,21 +3,16 @@ from django.test import TestCase from model_bakery import baker -def createCustomUser(): - return User.objects.create(username='Test') - -class TestModels(TestCase): - - def test_event_model(self): - task = baker.make(Todo, title="Sum2Prove") - self.assertEqual(str(task),"Sum2Prove") - - - def test_event_model(self): - task = baker.make(Todo, title="Sum2Prove") - self.assertEqual(str(task),"Sum2Prove") +def createCustomUser(): + return User.objects.create(username="Test") +class TestModels(TestCase): + def test_event_model(self): + task = baker.make(Todo, title="Sum2Prove") + self.assertEqual(str(task), "Sum2Prove") - \ No newline at end of file + def test_event_model(self): + task = baker.make(Todo, title="Sum2Prove") + self.assertEqual(str(task), "Sum2Prove") diff --git a/todo/tests/test_urls.py b/todo/tests/test_urls.py index a5582da..f820fda 100644 --- a/todo/tests/test_urls.py +++ b/todo/tests/test_urls.py @@ -1,35 +1,31 @@ from django.test import SimpleTestCase from django.urls import reverse, resolve -from todo.views import TodoCreateView, TodoDeleteView, TodoListView, TodoDetailView, TodoUpdateView - -class TestUrls(SimpleTestCase): - def test_list_url_is_resolves(self): - url = reverse('todo:list') - self.assertEquals(resolve(url).func.view_class, TodoListView) - - def test_list_url_is_resolves(self): - url = reverse('todo:detail', args = ['3']) - self.assertEquals(resolve(url).func.view_class, TodoDetailView) - - def test_list_url_is_resolves(self): - url = reverse('todo:create') - self.assertEquals(resolve(url).func.view_class, TodoCreateView) - - def test_list_url_is_resolves(self): - url = reverse('todo:delete', args = ['3']) - self.assertEquals(resolve(url).func.view_class, TodoDeleteView) - - def test_list_url_is_resolves(self): - url = reverse('todo:update', args = ['3']) - self.assertEquals(resolve(url).func.view_class, TodoUpdateView) - - - - - +from todo.views import ( + TodoCreateView, + TodoDeleteView, + TodoListView, + TodoDetailView, + TodoUpdateView, +) +class TestUrls(SimpleTestCase): + def test_list_url_is_resolves(self): + url = reverse("todo:list") + self.assertEquals(resolve(url).func.view_class, TodoListView) + def test_list_url_is_resolves(self): + url = reverse("todo:detail", args=["3"]) + self.assertEquals(resolve(url).func.view_class, TodoDetailView) + def test_list_url_is_resolves(self): + url = reverse("todo:create") + self.assertEquals(resolve(url).func.view_class, TodoCreateView) + def test_list_url_is_resolves(self): + url = reverse("todo:delete", args=["3"]) + self.assertEquals(resolve(url).func.view_class, TodoDeleteView) + def test_list_url_is_resolves(self): + url = reverse("todo:update", args=["3"]) + self.assertEquals(resolve(url).func.view_class, TodoUpdateView) diff --git a/todo/tests/test_views.py b/todo/tests/test_views.py index d4185f7..77f02f0 100644 --- a/todo/tests/test_views.py +++ b/todo/tests/test_views.py @@ -1 +1 @@ -from django.test import TestCase, Client \ No newline at end of file +from django.test import TestCase, Client diff --git a/todo/urls.py b/todo/urls.py index 2a2dee2..cd34c50 100644 --- a/todo/urls.py +++ b/todo/urls.py @@ -1,10 +1,11 @@ from django.urls import path from .views import TodoCreateView, TodoListView, TodoUpdateView, TodoDeleteView -app_name = 'todo' + +app_name = "todo" urlpatterns = [ - path('', TodoListView.as_view(), name='list'), - path('/', TodoUpdateView.as_view(), name='update'), - path('new/', TodoCreateView.as_view(), name='create'), - path('/delete/', TodoDeleteView.as_view(), name='delete') + path("", TodoListView.as_view(), name="list"), + path("/", TodoUpdateView.as_view(), name="update"), + path("new/", TodoCreateView.as_view(), name="create"), + path("/delete/", TodoDeleteView.as_view(), name="delete"), ] diff --git a/todo/views.py b/todo/views.py index 25f6468..87ad5ac 100644 --- a/todo/views.py +++ b/todo/views.py @@ -8,30 +8,33 @@ class TodoListView(PageTitleMixin, LoginRequiredMixin, ListView): model = Todo - context_object_name = 'todo' + context_object_name = "todo" paginate_by = 15 title = "Your Tasks" def get_queryset(self, *args, **kwargs): object_list = super(TodoListView, self).get_queryset(*args, **kwargs) - search = self.request.GET.get('q', None) + search = self.request.GET.get("q", None) if search: object_list = object_list.filter( - Q(title__icontains=search, user=self.request.user) | - Q(content__icontains=search, user=self.request.user) - ).order_by('created') + Q(title__icontains=search, user=self.request.user) + | Q(content__icontains=search, user=self.request.user) + ).order_by("created") return object_list else: - object_list = Todo.objects.filter( - user=self.request.user).order_by('created') + object_list = Todo.objects.filter(user=self.request.user).order_by( + "created" + ) return object_list -class TodoUpdateView(PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, UpdateView): +class TodoUpdateView( + PageTitleMixin, LoginRequiredMixin, UserPassesTestMixin, UpdateView +): model = Todo - success_url = reverse_lazy('todo:list') + success_url = reverse_lazy("todo:list") title = "Update Task" - fields = ['title', 'content'] + fields = ["title", "content"] def form_valid(self, form): form.instance.user = self.request.user @@ -45,7 +48,7 @@ def test_func(self): class TodoDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): model = Todo - success_url = reverse_lazy('todo:list') + success_url = reverse_lazy("todo:list") def get(self, request, *args, **kwargs): return self.post(request, *args, **kwargs) @@ -58,8 +61,8 @@ def test_func(self): class TodoCreateView(PageTitleMixin, LoginRequiredMixin, CreateView): model = Todo - fields = ['title', 'content'] - success_url = reverse_lazy('todo:list') + fields = ["title", "content"] + success_url = reverse_lazy("todo:list") title = "Create Task" def form_valid(self, form): diff --git a/users/admin.py b/users/admin.py index 850a1ad..123dd95 100755 --- a/users/admin.py +++ b/users/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin from .models import Profile + # Register your models here. -admin.site.register(Profile) \ No newline at end of file +admin.site.register(Profile) diff --git a/users/apps.py b/users/apps.py index b8d67f1..1322ac9 100755 --- a/users/apps.py +++ b/users/apps.py @@ -2,7 +2,7 @@ class UsersConfig(AppConfig): - name = 'users' + name = "users" def ready(self): import users.signals diff --git a/users/forms.py b/users/forms.py index f4384b8..b28dc8f 100755 --- a/users/forms.py +++ b/users/forms.py @@ -9,14 +9,16 @@ class UserUpdateForm(forms.ModelForm): class Meta: model = User - fields = ['username', 'email', 'first_name'] + fields = ["username", "email", "first_name"] class ProfileUpdateForm(forms.ModelForm): - class Meta: model = Profile - fields = ['image', 'about', 'githubusername'] + fields = ["image", "about", "githubusername"] labels = { - 'image': 'Profile Pic (500x500 is preferred resolution)', 'about': 'About you (max 200 words)', 'githubusername': 'Github Username ( if you wanna let others see it )'} - widgets = {'image': forms.FileInput()} + "image": "Profile Pic (500x500 is preferred resolution)", + "about": "About you (max 200 words)", + "githubusername": "Github Username ( if you wanna let others see it )", + } + widgets = {"image": forms.FileInput()} diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py index 31f0c49..5c23950 100644 --- a/users/migrations/0001_initial.py +++ b/users/migrations/0001_initial.py @@ -16,12 +16,35 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Profile', + name="Profile", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('image', models.ImageField(default='default.jpg', upload_to='profile_pics/', validators=[django.core.validators.validate_image_file_extension])), - ('slug', models.SlugField(null=True, unique=True)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "image", + models.ImageField( + default="default.jpg", + upload_to="profile_pics/", + validators=[ + django.core.validators.validate_image_file_extension + ], + ), + ), + ("slug", models.SlugField(null=True, unique=True)), + ( + "user", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/users/migrations/0002_profile_about.py b/users/migrations/0002_profile_about.py index 4bf5429..16ed7e1 100644 --- a/users/migrations/0002_profile_about.py +++ b/users/migrations/0002_profile_about.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0001_initial'), + ("users", "0001_initial"), ] operations = [ migrations.AddField( - model_name='profile', - name='about', + model_name="profile", + name="about", field=models.CharField(blank=True, max_length=200, null=True), ), ] diff --git a/users/migrations/0003_auto_20200724_2225.py b/users/migrations/0003_auto_20200724_2225.py index 1944b6f..8cde415 100644 --- a/users/migrations/0003_auto_20200724_2225.py +++ b/users/migrations/0003_auto_20200724_2225.py @@ -7,13 +7,18 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0002_profile_about'), + ("users", "0002_profile_about"), ] operations = [ migrations.AlterField( - model_name='profile', - name='image', - field=models.ImageField(default='default.jpg', null='True', upload_to='profile_pics/', validators=[django.core.validators.validate_image_file_extension]), + model_name="profile", + name="image", + field=models.ImageField( + default="default.jpg", + null="True", + upload_to="profile_pics/", + validators=[django.core.validators.validate_image_file_extension], + ), ), ] diff --git a/users/migrations/0004_auto_20200724_2226.py b/users/migrations/0004_auto_20200724_2226.py index 8ca6cb4..097632e 100644 --- a/users/migrations/0004_auto_20200724_2226.py +++ b/users/migrations/0004_auto_20200724_2226.py @@ -7,13 +7,19 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0003_auto_20200724_2225'), + ("users", "0003_auto_20200724_2225"), ] operations = [ migrations.AlterField( - model_name='profile', - name='image', - field=models.ImageField(blank=True, default='default.jpg', null=True, upload_to='profile_pics/', validators=[django.core.validators.validate_image_file_extension]), + model_name="profile", + name="image", + field=models.ImageField( + blank=True, + default="default.jpg", + null=True, + upload_to="profile_pics/", + validators=[django.core.validators.validate_image_file_extension], + ), ), ] diff --git a/users/migrations/0005_profile_points.py b/users/migrations/0005_profile_points.py index 2c4ad61..88d8ce4 100644 --- a/users/migrations/0005_profile_points.py +++ b/users/migrations/0005_profile_points.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0004_auto_20200724_2226'), + ("users", "0004_auto_20200724_2226"), ] operations = [ migrations.AddField( - model_name='profile', - name='points', + model_name="profile", + name="points", field=models.IntegerField(default=0), ), ] diff --git a/users/migrations/0006_profile_githubusername.py b/users/migrations/0006_profile_githubusername.py index 339b1a2..8ab45c9 100644 --- a/users/migrations/0006_profile_githubusername.py +++ b/users/migrations/0006_profile_githubusername.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0005_profile_points'), + ("users", "0005_profile_points"), ] operations = [ migrations.AddField( - model_name='profile', - name='githubusername', + model_name="profile", + name="githubusername", field=models.CharField(blank=True, max_length=60, null=True), ), ] diff --git a/users/migrations/0007_auto_20200731_0018.py b/users/migrations/0007_auto_20200731_0018.py index 98bf1da..60f7b68 100644 --- a/users/migrations/0007_auto_20200731_0018.py +++ b/users/migrations/0007_auto_20200731_0018.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0006_profile_githubusername'), + ("users", "0006_profile_githubusername"), ] operations = [ migrations.RenameField( - model_name='profile', - old_name='githubusername', - new_name='githuburl', + model_name="profile", + old_name="githubusername", + new_name="githuburl", ), ] diff --git a/users/migrations/0008_auto_20200731_0021.py b/users/migrations/0008_auto_20200731_0021.py index a4c0d3d..2ea44db 100644 --- a/users/migrations/0008_auto_20200731_0021.py +++ b/users/migrations/0008_auto_20200731_0021.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0007_auto_20200731_0018'), + ("users", "0007_auto_20200731_0018"), ] operations = [ migrations.RenameField( - model_name='profile', - old_name='githuburl', - new_name='githubusername', + model_name="profile", + old_name="githuburl", + new_name="githubusername", ), ] diff --git a/users/migrations/0009_auto_20200803_0249.py b/users/migrations/0009_auto_20200803_0249.py index aab7494..f054ce1 100644 --- a/users/migrations/0009_auto_20200803_0249.py +++ b/users/migrations/0009_auto_20200803_0249.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0008_auto_20200731_0021'), + ("users", "0008_auto_20200731_0021"), ] operations = [ migrations.RenameField( - model_name='profile', - old_name='points', - new_name='domes', + model_name="profile", + old_name="points", + new_name="domes", ), ] diff --git a/users/migrations/0010_auto_20200805_2110.py b/users/migrations/0010_auto_20200805_2110.py index 0d0b665..9282f49 100644 --- a/users/migrations/0010_auto_20200805_2110.py +++ b/users/migrations/0010_auto_20200805_2110.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0009_auto_20200803_0249'), + ("users", "0009_auto_20200803_0249"), ] operations = [ migrations.AlterField( - model_name='profile', - name='slug', + model_name="profile", + name="slug", field=models.SlugField(max_length=256, null=True, unique=True), ), ] diff --git a/users/migrations/0011_auto_20200810_1515.py b/users/migrations/0011_auto_20200810_1515.py index 8acb3ea..c758fc3 100644 --- a/users/migrations/0011_auto_20200810_1515.py +++ b/users/migrations/0011_auto_20200810_1515.py @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0010_auto_20200805_2110'), + ("users", "0010_auto_20200805_2110"), ] operations = [ migrations.AlterField( - model_name='profile', - name='githubusername', + model_name="profile", + name="githubusername", field=models.CharField(blank=True, max_length=80, null=True), ), ] diff --git a/users/models.py b/users/models.py index 352ef09..da544b7 100755 --- a/users/models.py +++ b/users/models.py @@ -7,34 +7,40 @@ class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) - image = models.ImageField(null=True, blank=True, - default='default.jpg', upload_to='profile_pics/', validators=[validate_image_file_extension]) + image = models.ImageField( + null=True, + blank=True, + default="default.jpg", + upload_to="profile_pics/", + validators=[validate_image_file_extension], + ) about = models.CharField(null=True, blank=True, max_length=200) githubusername = models.CharField(null=True, blank=True, max_length=80) domes = models.IntegerField(default=0) slug = models.SlugField(null=True, unique=True, max_length=256) def __str__(self): - return f'{self.user.username} Profile' + return f"{self.user.username} Profile" def get_absolute_url(self): - return reverse_lazy('users:profilepage', kwargs={'slug': self.slug}) + return reverse_lazy("users:profilepage", kwargs={"slug": self.slug}) def save(self, *args, **kwargs): username = self.user.username self.slug = slugify(username) super().save(*args, **kwargs) - # img = Image.open(self.image.path) + +# img = Image.open(self.image.path) # if img.height > 500 and img.width > 500: - # img = img.resize((500, 500), Image.ANTIALIAS) - # img.save(self.image.path, quality=90) +# img = img.resize((500, 500), Image.ANTIALIAS) +# img.save(self.image.path, quality=90) # if img.height > 500 and img.width < 500: - # img = img.resize((img.width, img.width), Image.ANTIALIAS) - # img.save(self.image.path, quality=90) +# img = img.resize((img.width, img.width), Image.ANTIALIAS) +# img.save(self.image.path, quality=90) # if img.height < 500 and img.width > 500: - # img = img.resize((img.height, img.height), Image.ANTIALIAS) - # img.save(self.image.path, quality=90) +# img = img.resize((img.height, img.height), Image.ANTIALIAS) +# img.save(self.image.path, quality=90) diff --git a/users/signals.py b/users/signals.py index b27bbc8..818b0ab 100755 --- a/users/signals.py +++ b/users/signals.py @@ -3,6 +3,7 @@ from django.dispatch import receiver from .models import Profile + @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: diff --git a/users/urls.py b/users/urls.py index 6b68b7b..265cc61 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,12 +1,12 @@ from django.urls import path from . import views from users.views import AccountDetailView, Leaderboard -app_name = 'users' -urlpatterns = [ - path('leaderboard/', Leaderboard.as_view(), name='leaderboard'), - path('profile/register/', views.signup, name='register'), - path('profile/edit/', views.profile, name='profile'), - path('user//', AccountDetailView.as_view(), name='profilepage'), +app_name = "users" +urlpatterns = [ + path("leaderboard/", Leaderboard.as_view(), name="leaderboard"), + path("profile/register/", views.signup, name="register"), + path("profile/edit/", views.profile, name="profile"), + path("user//", AccountDetailView.as_view(), name="profilepage"), ] diff --git a/users/views.py b/users/views.py index 5ac0809..efabacf 100755 --- a/users/views.py +++ b/users/views.py @@ -9,40 +9,40 @@ def signup(request): - return render(request, "users/register.html", {'title': 'Register'}) + return render(request, "users/register.html", {"title": "Register"}) class Leaderboard(PageTitleMixin, ListView): model = Profile template_name = "users/leaderboard.html" title = "Leaderboard" - context_object_name = 'profile' + context_object_name = "profile" def get_queryset(self, *args, **kwargs): - object_list = super( - Leaderboard, self).get_queryset(*args, **kwargs) - return object_list.order_by('-domes')[:100] + object_list = super(Leaderboard, self).get_queryset(*args, **kwargs) + return object_list.order_by("-domes")[:100] -@ login_required +@login_required def profile(request): - if request.method == 'POST': + if request.method == "POST": u_form = UserUpdateForm(request.POST, instance=request.user) p_form = ProfileUpdateForm( - request.POST, request.FILES, instance=request.user.profile) + request.POST, request.FILES, instance=request.user.profile + ) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() - messages.success(request, f'Your profile has been updated!') - return redirect('users:profile') + messages.success(request, f"Your profile has been updated!") + return redirect("users:profile") else: u_form = UserUpdateForm(instance=request.user) p_form = ProfileUpdateForm(instance=request.user.profile) - context = {'u_form': u_form, 'p_form': p_form} - return render(request, 'users/profile.html', context) + context = {"u_form": u_form, "p_form": p_form} + return render(request, "users/profile.html", context) class AccountDetailView(PageTitleMixin, LoginRequiredMixin, DetailView): model = Profile - title = 'User Profile' + title = "User Profile" template_name = "users/profilepage.html" From 9703ee2a3795a38e9fe7d1c7fa9e5a36940ba379 Mon Sep 17 00:00:00 2001 From: Arth Tyagi Date: Wed, 23 Sep 2020 01:10:51 +0530 Subject: [PATCH 08/63] Update codeql-analysis.yml --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2401b81..73a5d3b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -19,7 +19,7 @@ jobs: matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] - language: ['python', 'javascript', 'java', 'cpp', 'go'] + language: ['python'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection From 59664cdc8be8c2195cde9cdc13c4c71847987fdf Mon Sep 17 00:00:00 2001 From: Arth Tyagi Date: Wed, 23 Sep 2020 01:12:35 +0530 Subject: [PATCH 09/63] updated readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 51ffcc8..462c21e 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,14 @@ Unreleased features are **highlighted**. Note : In the repo's language stats, HTML and CSS have been disabled intentionally. +## Workflows on this repository + +- Django CI is on the Private codebase. +- Greetings Workflow +- Codeql Code Analysis workflow +- Python Lint +- PR Labeler + ## 🧑 Contributors - [Arth Tyagi](https://github.com/arthtyagi) - Founder, CEO, Full Stack Developer, [DomeCode](https://domecode.com/) From 8eb823e1bb909fcbe1f53613e25fe47d7f084c7c Mon Sep 17 00:00:00 2001 From: charlygg Date: Fri, 25 Sep 2020 02:31:07 -0500 Subject: [PATCH 10/63] Syntax highlighting added in fusion editor --- fusion/templates/fusion/fusion_detail.html | 28 +- notes/static/js/codemirror.js | 9788 ++++++++++++++++++++ notes/static/js/comment.js | 211 + notes/static/js/continuecomment.js | 114 + notes/static/js/css-hint.js | 66 + notes/static/js/css.js | 863 ++ notes/static/js/editor.js | 32 + notes/static/js/htmlembedded.js | 37 + notes/static/js/htmlmixed.js | 152 + notes/static/js/javascript.js | 934 ++ notes/static/js/matchbrackets.js | 158 + notes/static/js/placeholder.js | 77 + notes/static/js/script.js | 6 +- notes/static/js/selection-pointer.js | 98 + notes/static/js/show-hint.js | 479 + notes/static/js/vbscript.js | 350 + notes/static/js/xml.js | 413 + notes/static/notes/codemirror.css | 350 + notes/static/notes/show-hint.css | 36 + 19 files changed, 14187 insertions(+), 5 deletions(-) create mode 100644 notes/static/js/codemirror.js create mode 100644 notes/static/js/comment.js create mode 100644 notes/static/js/continuecomment.js create mode 100644 notes/static/js/css-hint.js create mode 100644 notes/static/js/css.js create mode 100644 notes/static/js/htmlembedded.js create mode 100644 notes/static/js/htmlmixed.js create mode 100644 notes/static/js/javascript.js create mode 100644 notes/static/js/matchbrackets.js create mode 100644 notes/static/js/placeholder.js create mode 100644 notes/static/js/selection-pointer.js create mode 100644 notes/static/js/show-hint.js create mode 100644 notes/static/js/vbscript.js create mode 100644 notes/static/js/xml.js create mode 100644 notes/static/notes/codemirror.css create mode 100644 notes/static/notes/show-hint.css diff --git a/fusion/templates/fusion/fusion_detail.html b/fusion/templates/fusion/fusion_detail.html index e19f4a3..d074650 100644 --- a/fusion/templates/fusion/fusion_detail.html +++ b/fusion/templates/fusion/fusion_detail.html @@ -2,7 +2,6 @@ - DomeCode - Fusion @@ -68,11 +67,36 @@ + + + + + + + + + + + + + + + + + + + + +