diff --git a/.github/workflows/canopeum_backend.yml b/.github/workflows/canopeum_backend.yml index 2135cdb0e..4d6e937a4 100644 --- a/.github/workflows/canopeum_backend.yml +++ b/.github/workflows/canopeum_backend.yml @@ -54,3 +54,4 @@ jobs: - uses: jakebailey/pyright-action@v2 with: python-version: "3.12" + working-directory: canopeum_backend diff --git a/README.md b/README.md index 2fc53894f..7c66208be 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,15 @@ For backend cd releaf-canopeum ``` -3. Set up a Python 3.12 virtual environment +3. Install recommended Editor Extensions (for VSCode):\ + When you first open the project in VSCode, you'll get a notification like this.\ + ![Recommended Popup](/docs/Recommended_Popup.png) + + If you've already dismissed this notification, you can search for `@recommended` in your Extensions tab. + Install everything under "**WORKSPACE RECOMMENDATIONS**", you can ignore "other recommendations":\ + ![Recommended Extensions](/docs/Recommended_Extensions.png) + +4. Set up a Python 3.12 virtual environment ```shell cd canopeum_backend @@ -64,7 +72,7 @@ For backend `CTRL+Shift+P` (Open Command Palette) > `Python: Select Interpreter` ![VSCode_select_venv](/docs/VSCode_select_venv.png) -4. Set up Django backend and Database: (Skip this section for Frontend only) +5. Set up Django backend and Database: (Skip this section for Frontend only) ```shell docker compose up @@ -74,7 +82,7 @@ For backend python manage.py runserver ``` -5. Set up React frontend: +6. Set up React frontend: ```shell cd canopeum_frontend diff --git a/canopeum_backend/canopeum_backend/serializers.py b/canopeum_backend/canopeum_backend/serializers.py index 52b50c405..19e098f10 100644 --- a/canopeum_backend/canopeum_backend/serializers.py +++ b/canopeum_backend/canopeum_backend/serializers.py @@ -59,7 +59,7 @@ class SiteTypeSerializer(serializers.ModelSerializer): class Meta: model = Sitetype - fields = ["id", "en", "fr"] + fields = ("id", "en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.name).data.get("en", None) @@ -74,7 +74,7 @@ class TreeTypeSerializer(serializers.ModelSerializer): class Meta: model = Treetype - fields = ["en", "fr"] + fields = ("en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.name).data.get("en", None) @@ -149,7 +149,7 @@ class BatchfertilizerSerializer(serializers.ModelSerializer): class Meta: model = Batchfertilizer - fields = ["id", "en", "fr"] + fields = ("id", "en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.fertilizer_type).data.get("en", None) @@ -164,7 +164,7 @@ class BatchMulchLayerSerializer(serializers.ModelSerializer): class Meta: model = Mulchlayertype - fields = ["id", "en", "fr"] + fields = ("id", "en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.mulch_layer_type).data.get("en", None) @@ -179,7 +179,7 @@ class BatchSupportedSpeciesSerializer(serializers.ModelSerializer): class Meta: model = BatchSupportedSpecies - fields = ["en", "fr"] + fields = ("en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.tree_type).data.get("en", None) @@ -194,7 +194,7 @@ class BatchSeedSerializer(serializers.ModelSerializer): class Meta: model = BatchSeed - fields = ["quantity", "en", "fr"] + fields = ("quantity", "en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.tree_type).data.get("en", None) @@ -209,7 +209,7 @@ class BatchSpeciesSerializer(serializers.ModelSerializer): class Meta: model = BatchSpecies - fields = ["quantity", "en", "fr"] + fields = ("quantity", "en", "fr") def get_en(self, obj): return InternationalizationSerializer(obj.tree_type).data.get("en", None) diff --git a/canopeum_backend/canopeum_backend/views.py b/canopeum_backend/canopeum_backend/views.py index 6a2cf772c..0eb7364ac 100644 --- a/canopeum_backend/canopeum_backend/views.py +++ b/canopeum_backend/canopeum_backend/views.py @@ -1,5 +1,4 @@ -from typing import ClassVar - +from django.contrib.auth import authenticate from django.contrib.auth.models import User from drf_spectacular.utils import extend_schema from rest_framework import status @@ -28,7 +27,7 @@ class LoginAPIView(APIView): - permission_classes: ClassVar[list[type[AllowAny]]] = [AllowAny] + permission_classes = (AllowAny,) @extend_schema(request=AuthUserSerializer, responses=UserSerializer, operation_id="authentication_login") def post(self, request): @@ -43,7 +42,7 @@ def post(self, request): class RegisterAPIView(APIView): - permission_classes: ClassVar[list[type[AllowAny]]] = [AllowAny] + permission_classes = (AllowAny,) @extend_schema(request=UserSerializer, responses=AuthUserSerializer, operation_id="authentication_register") def post(self, request): @@ -183,10 +182,7 @@ def get(self, request): class PostListAPIView(APIView): @extend_schema(responses=PostSerializer(many=True), operation_id="post_all") def get(self, request): - try: - comment_count = Comment.objects.get(post=request.data.get("id")).count() - except Comment.DoesNotExist: - comment_count = 0 + comment_count = Comment.objects.filter(post=request.data.get("id")).count() has_liked = 0 posts = Post.objects.all() serializer = PostSerializer(posts, many=True, context={"comment_count": comment_count, "has_liked": has_liked}) diff --git a/canopeum_backend/pyproject.toml b/canopeum_backend/pyproject.toml index 83722d4e0..666928fe3 100644 --- a/canopeum_backend/pyproject.toml +++ b/canopeum_backend/pyproject.toml @@ -71,10 +71,9 @@ ignore = [ ### https://github.com/astral-sh/ruff/issues/1256 & https://github.com/astral-sh/ruff/issues/1774): "DJ001", # Avoid using `null=True` on string-based fields "DJ008", # Model does not define `__str__` method: https://docs.astral.sh/ruff/rules/django-model-without-dunder-str/ + "N803", # Different naming convention between js/json and python. A better/configured middleware could take care of that ] -[tool.ruff.format] - # https://docs.astral.sh/ruff/settings/#flake8-implicit-str-concat [tool.ruff.lint.flake8-implicit-str-concat] allow-multiline = false @@ -100,6 +99,8 @@ max-branches = 15 pythonVersion = "3.12" exclude = [".venv/"] typeCheckingMode = "standard" +# django-specific mypy plugin does a better job getting serializers data type of dict vs list +reportAttributeAccessIssue = "none" # https://mypy.readthedocs.io/en/stable/config_file.html [tool.mypy] diff --git a/docs/Recommended_Extensions.png b/docs/Recommended_Extensions.png new file mode 100644 index 000000000..78a4e2997 Binary files /dev/null and b/docs/Recommended_Extensions.png differ diff --git a/docs/Recommended_Popup.png b/docs/Recommended_Popup.png new file mode 100644 index 000000000..49a5b68e7 Binary files /dev/null and b/docs/Recommended_Popup.png differ