diff --git a/.env b/.env new file mode 100644 index 0000000..6c2eaba --- /dev/null +++ b/.env @@ -0,0 +1 @@ +MANAGE_PY_PATH=manage.py diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100644 index 0000000..a51cddc --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,19 @@ +#!/bin/bash + +echo "Running tests with coverage..." + +coverage run manage.py test +status=$? + +if [ $status -ne 0 ]; then + echo "โŒ Tests failed. Push aborted." + exit 1 +fi + +coverage report --fail-under=85 # set your threshold +if [ $? -ne 0 ]; then + echo "โŒ Coverage is below threshold. Push aborted." + exit 1 +fi + +echo "โœ… Tests passed and coverage is acceptable. Proceeding with push." diff --git a/.github/workflows/basic-checks.yaml b/.github/workflows/basic-checks.yaml new file mode 100644 index 0000000..cef4d8b --- /dev/null +++ b/.github/workflows/basic-checks.yaml @@ -0,0 +1,42 @@ +name: ๐Ÿšฆ Basic Checks + +on: + push: + branches: + - main + pull_request: + +jobs: + quality-checks: + name: Quality Checks + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“ฅ Checkout code + uses: actions/checkout@v4 + + - name: ๐Ÿ Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: ๐Ÿ“ฆ Install dependencies + run: pip install -r requirements.txt + + - name: ๐ŸŽจ Run black (formatting) + run: black --check . + + - name: ๐Ÿงน Run isort (import sorting) + run: isort --check-only . + + - name: ๐Ÿง Run mypy (type checking) + run: mypy . + + - name: ๐Ÿ” Run pylint (linting) + run: pylint **/*.py + + - name: ๐Ÿงช Run tests with coverage + run: coverage run manage.py test + + - name: ๐Ÿ“Š Generate coverage report (fail if <85%) + run: coverage report --fail-under=85 diff --git a/.gitignore b/.gitignore index 033df5f..51fcfd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .venv -__pycache__ +__pycache__/ +*sqlite3 +.coverage +htmlcov diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index c31706b..0000000 --- a/.isort.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[settings] -verbose = true -skip_glob = **/migrations/* \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..375c4f9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,52 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + + - repo: https://github.com/psf/black + rev: 25.1.0 + hooks: + - id: black + name: black to format python code + + - repo: https://github.com/pycqa/isort + rev: 6.0.1 + hooks: + - id: isort + name: isort to sort imports + args: + - --profile + - black + - --verbose + - --skip-glob + - "**/migrations/*.py" + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.17.0 + hooks: + - id: mypy + name: mypy to check types + additional_dependencies: + - django-jazzmin==3.0.1 + - django-stubs==5.2.2 + - djangorestframework==3.16.0 + - djangorestframework-stubs==3.16.1 + args: ["--config-file=mypy.ini"] + + - repo: https://github.com/pycqa/pylint + rev: v3.3.7 + hooks: + - id: pylint + name: pylint to check code quality + entry: pylint + language: python + types: [python] + args: ["--rcfile=.pylintrc"] + additional_dependencies: + - django-jazzmin==3.0.1 + - Django==5.2.4 + - pylint-django==2.6.1 + - djangorestframework==3.16.0 diff --git a/.pylintrc b/.pylintrc index de881a9..2a296a9 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,6 +5,10 @@ # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no +# Clear in-memory caches upon conclusion of linting. Useful if running pylint +# in a server-like mode. +clear-cache-post-run=no + # Load and enable all available extensions. Use --list-extensions to see a list # all available extensions. #enable-all-extensions= @@ -46,9 +50,9 @@ ignore=CVS # Add files or directories matching the regular expressions patterns to the # ignore-list. The regex matches against paths and can be in Posix or Windows -# format. Because '\' represents the directory delimiter on Windows systems, it -# can't be used as an escape character. -ignore-paths= +# format. Because '\\' represents the directory delimiter on Windows systems, +# it can't be used as an escape character. +ignore-paths=.*/migrations # Files or directories matching the regular expression patterns are skipped. # The regex matches against base names, not paths. The default value ignores @@ -89,6 +93,12 @@ py-version=3.10 # Discover python modules and packages in the file system subtree. recursive=no +# Add paths to the list of the source roots. Supports globbing patterns. The +# source root is an absolute path or a path relative to the current working +# directory used to determine a package namespace for modules located under the +# source root. +source-roots= + # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. suggestion-mode=yes @@ -224,6 +234,10 @@ no-docstring-rgx=^_ # These decorators are taken in consideration only for invalid-name. property-classes=abc.abstractproperty +# Regular expression matching correct type alias names. If left empty, type +# alias names will be checked with the set naming style. +#typealias-rgx= + # Regular expression matching correct type variable names. If left empty, type # variable names will be checked with the set naming style. #typevar-rgx= @@ -246,21 +260,18 @@ check-protected-access-in-special-methods=no defining-attr-methods=__init__, __new__, setUp, + asyncSetUp, __post_init__ # List of member names, which should be excluded from the protected access # warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=cls +valid-metaclass-classmethod-first-arg=mcs [DESIGN] @@ -307,8 +318,7 @@ min-public-methods=2 [EXCEPTIONS] # Exceptions that will emit a warning when caught. -overgeneral-exceptions=BaseException, - Exception +overgeneral-exceptions=builtins.BaseException,builtins.Exception [FORMAT] @@ -347,6 +357,9 @@ single-line-if-stmt=no # one. allow-any-import-level= +# Allow explicit reexports by alias from a package __init__. +allow-reexport-from-package=no + # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no @@ -416,14 +429,18 @@ disable=raw-checker-failed, useless-suppression, deprecated-pragma, use-symbolic-message-instead, - import-outside-toplevel - + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero, + missing-module-docstring, + import-outside-toplevel, + fixme + # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member +enable= [METHOD_ARGS] @@ -469,8 +486,9 @@ evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor # used to format the message information. See doc for all details. msg-template= -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. #output-format= @@ -504,8 +522,8 @@ min-similarity-lines=4 # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 -# Spelling dictionary name. Available dictionaries: none. To make it work, -# install the 'python-enchant' package. +# Spelling dictionary name. No available dictionaries : You need to install +# both the python package and the system dependency for enchant to work. spelling-dict= # List of comma separated words that should be considered directives if they @@ -622,4 +640,4 @@ redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io # pylint_django configuration [pylint-django] -django-settings-module=django_starter.settings \ No newline at end of file +django-settings-module=backend.settings diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..60a76d6 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + "recommendations": [ + "ms-python.python", + "esbenp.prettier-vscode", + "ms-python.black-formatter", + "ms-python.isort", + "ms-python.mypy-type-checker", + "batisteo.vscode-django", + "ms-python.pylint", + "ms-python.debugpy", + "ms-python.vscode-pylance", + "yy0931.vscode-sqlite3-editor", + "streetsidesoftware.code-spell-checker" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8923697..5cf0c19 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,22 +1,19 @@ { - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll": true, - "source.organizeImports": true, - }, - "isort.args": [ - "skip_glob", - "*/migrations/*", - ], - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - }, - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.linting.pylintArgs": [ - "--load-plugins", - "pylint_django", - "django-settings-module=django_starter.settings", - ], - "python.linting.mypyEnabled": true, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.unusedImports": "explicit", + "source.organizeImports": "explicit" + }, + "editor.rulers": [100], + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "isort.args": ["--profile", "black", "--skip-glob", "*/migrations/*"], + "python.testing.unittestEnabled": true, + "python.testing.pytestEnabled": false, + "python.testing.unittestArgs": ["-p", "*test*.py"] } diff --git a/README.md b/README.md index d3dec14..1d081cb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Django Starter Project -Create Virtual Environment +1. Create Virtual Environment - if windows @@ -14,7 +14,7 @@ Create Virtual Environment python3 -m venv .venv ``` -Activate Virtual Environment +2. Activate Virtual Environment - if windows @@ -28,241 +28,1088 @@ Activate Virtual Environment source .venv/bin/activate ``` -- if you want to deactivate +- Note:- if you want to deactivate ```bash deactivate ``` -Install Django +3. Setup Django project -```bash -pip install django -``` - -Create Django Project +- Install Django package -```bash -django-admin startproject -``` + ```sh + pip install Django + ``` -Run Django Project +- Add installed Django package to requirements file -```bash -python manage.py runserver -``` + ```sh + pip freeze | grep Django > requirements.txt + ``` -Setup Pylint +- Start Django project -- Reference Links + ```sh + django-admin startproject . + ``` - - [pylint](https://github.com/PyCQA/pylint/) +4. Setup Django app - - [pylint-django](https://github.com/PyCQA/pylint-django/) +- Start Django app - - Blog: [How to setup pylint for django project](https://dkolodzey.medium.com/pylint-django-with-github-actions-2e3ef05dd34a) + ```sh + python3 manage.py startapp + ``` -- Install pylint for code analysis and linting +- Install Django app in project setting - ```bash - pip install pylint + ```python + INSTALLED_APPS = [ + ..., + '', + ] ``` -- Install pylint-django pylint plugin +5. Setup Django Model - ```bash - pip install pylint-django +- Generate migration file for model + + ```sh + python3 manage.py makemigrations ``` -- Create pylint config file if you want to customize +- Apply migration - ```bash - pylint --generate-rcfile > .pylintrc + ```sh + python3 manage.py migrate ``` - +```sh +python3 manage.py test +``` -- Add pylint_django in load-plugins to pylint config file +7. Setup DRF(Django Rest Framework) - ```text - [MASTER] - load-plugins=pylint_django +- Install DRF package + + ```sh + pip install djangorestframework ``` -- Add django settings module in pylint config file +- Add installed DRF package to requirements file - ```text - [pylint-django] - django-settings-module=.settings + ```sh + pip freeze | grep djangorestframework >> requirements.txt ``` -- Run pylint +- Install DRF app in project setting - ```bash - pylint **/*.py + ```python + INSTALLED_APPS = [ + ..., + 'rest_framework', + ] ``` -- NOTE: if you not want to create pylint config file, you can run pylint with +8. Setup Test Coverage -```bash -pylint --load-plugins=pylint_django --django-settings-module=.settings **/*.py -``` +- Install Coverage package -TODO - Fix this is not working + ```sh + pip install coverage + ``` -- If you are using vscode, you can install pylint extension and it will automatically run pylint on save. for that you need to add this in settings.json +- Add installed Coverage package to requirements file - ```json - { - { - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.linting.pylintArgs": [ - "--load-plugins", - "pylint_django", - "--django-settings-module=.settings" - ] - } + ```sh + pip freeze | grep coverage >> requirements.txt ``` - [Setup Reference Links](https://dkolodzey.medium.com/pylint-for-django-in-vscode-f3fadb8462d) +- Run tests with coverage -Setup Black for code formatting + ```sh + coverage run manage.py test + ``` -- Reference Links +- See coverage report on terminal - - [black](https://black.readthedocs.io/en/stable/) - - [Blog Link](https://ctrlzblog.com/how-to-set-up-black-to-automatically-format-your-django-project/) + ```sh + coverage report + ``` -- Install black +- Generate HTML report - ```bash - pip install black + ```sh + coverage html ``` -- Run black +9. Setup MyPy - ```bash - black . +- Install MyPy package + + ```sh + pip install mypy ``` -- Check black formatting +- Add installed mypy package to requirements file - ```bash - black --check . + ```sh + pip freeze | grep mypy== >> requirements.txt ``` -- If you are using vscode +- Install django stubs package - - Install VS Code Extension `ms-python.black-formatter` + ```sh + pip install django-stubs + ``` - - add this in settings.json - ```json - { - "editor.formatOnSave": true, - "python.formatting.provider": "black" - } - ``` +- Add installed django stubs package to requirements file -Setup mypy for static type checking + ```sh + pip freeze | grep django-stubs== >> requirements.txt + ``` -- Reference Links +- Install drf stubs package - - [mypy](https://mypy.readthedocs.io/en/stable/) - - [django-stubs github repo](https://github.com/typeddjango/django-stubs) + ```sh + pip install djangorestframework-stubs + ``` -- Install mypy +- Add installed drf stubs package to requirements file - ```bash - pip install mypy - ``` + ```sh + pip freeze | grep djangorestframework-stubs >> requirements.txt + ``` -- Install django-stubs for django type checking +- Add MyPy config file `mypy.init` - ```bash - pip install django-stubs - ``` + ```init + [mypy] + plugins = mypy_django_plugin.main + exclude = migrations|tests -- Note this is not required in current case, but if you are using django models, you need to install django-stubs + [mypy.plugins.django-stubs] + django_settings_module = ".settings" + ``` - - [mypy config docs](https://mypy.readthedocs.io/en/latest/config_file.html) - - [Stack Overflow Reference](https://stackoverflow.com/questions/59031982/type-annotations-for-django-models) +- Note:- config file [doc](https://mypy.readthedocs.io/en/latest/config_file.html) - - Add django-stubs in plugins in mypy config file `mypy.ini` +- Run mypy type checking - ```text - [mypy] - plugins = mypy_django_plugin.main - ``` + ```sh + mypy . + ``` - - Add django settings module in mypy config file `mypy.ini` - ```text - [mypy.plugins.django-stubs] - django_settings_module = .settings - ``` +10. Setup black -- Run mypy +- Install black package - ```bash - mypy . + ```sh + pip install black + ``` + +- Add installed black package to requirements file + ```sh + pip freeze | grep black >> requirements.txt ``` -- If you are using vscode, you need to add this in settings.json +- Add black config in `puproject.toml` file - ```json - { - "python.linting.mypyEnabled": true, - "python.linting.mypyArgs": ["--strict"] - } + ```toml + [tool.black] + force-exclude = "/migrations/" ``` -- [Reference Blog](https://dev.to/jodaut/python-type-checking-with-visual-studio-code-46a7) +- Note:- black official [doc](https://black.readthedocs.io/en/stable/getting_started.html) -Setup isort for sorting imports +- Install VS Code Black extension [`ms-python.black-formatter`](https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter) -- Reference Links +- Configure VS Code python default formatter to black in `.vscode/settings.json` file - - [isort](https://pycqa.github.io/isort/) - - [github wiki](https://github.com/PyCQA/isort/wiki/isort-Settings) + ```json + { + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + } + } + ``` -- Install isort +- Fix formatting using black - ```bash - pip install isort + ```sh + black . ``` -- Run isort +11. Setup isort - ```bash - isort . +- Install isort package + + ```sh + pip install isort ``` -- Check isort +- Add installed isort package to requirements file - ```bash - isort --check . + ```sh + pip freeze | grep isort >> requirements.txt ``` -- If want to customize isort, you can create isort config file `isort.cfg` +- Add isort config file `isort.cfg` - ```text + ```cfg [settings] + profile = black verbose = true skip_glob = **/migrations/*.py ``` -- NOTE: supported options are [here](https://pycqa.github.io/isort/docs/configuration/options.html) +- Install VS Code isort extension [`ms-python.isort`](https://marketplace.visualstudio.com/items?itemName=ms-python.isort) -- If you are using vscode, you need to add this in settings.json +- Configure VS Code to organize python imports using isort in `.vscode/settings.json` ```json { "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.unusedImports": "explicit", + "source.organizeImports": "explicit" }, - "isort.args": ["skip_glob", "*/migrations/*"] + "isort.args": ["--profile", "black", "--skip-glob", "*/migrations/*"] } ``` + +- Sort imports using isort + + ```sh + isort . + ``` + +12. Setup pylint + +- Install pylint package + + ```sh + pip install pylint + ``` + +- Add installed pylint package to requirements file + + ```sh + pip freeze | grep pylint== >> requirements.txt + ``` + +- Install pylint-django package + + ```sh + pip install pylint-django + ``` + +- Add installed pylint-django package to requirements file + + ```sh + pip freeze | grep pylint-django >> requirements.txt + ``` + +- Add pylint config file `.pylintrc` + + ```pylintrc + [MAIN] + + # Analyse import fallback blocks. This can be used to support both Python 2 and + # 3 compatible code, which means that the block might have code that exists + # only in one or another interpreter, leading to false positives when analysed. + analyse-fallback-blocks=no + + # Clear in-memory caches upon conclusion of linting. Useful if running pylint + # in a server-like mode. + clear-cache-post-run=no + + # Load and enable all available extensions. Use --list-extensions to see a list + # all available extensions. + #enable-all-extensions= + + # In error mode, messages with a category besides ERROR or FATAL are + # suppressed, and no reports are done by default. Error mode is compatible with + # disabling specific errors. + #errors-only= + + # Always return a 0 (non-error) status code, even if lint errors are found. + # This is primarily useful in continuous integration scripts. + #exit-zero= + + # A comma-separated list of package or module names from where C extensions may + # be loaded. Extensions are loading into the active Python interpreter and may + # run arbitrary code. + extension-pkg-allow-list= + + # A comma-separated list of package or module names from where C extensions may + # be loaded. Extensions are loading into the active Python interpreter and may + # run arbitrary code. (This is an alternative name to extension-pkg-allow-list + # for backward compatibility.) + extension-pkg-whitelist= + + # Return non-zero exit code if any of these messages/categories are detected, + # even if score is above --fail-under value. Syntax same as enable. Messages + # specified are enabled, while categories only check already-enabled messages. + fail-on= + + # Specify a score threshold under which the program will exit with error. + fail-under=10 + + # Interpret the stdin as a python script, whose filename needs to be passed as + # the module_or_package argument. + #from-stdin= + + # Files or directories to be skipped. They should be base names, not paths. + ignore=CVS + + # Add files or directories matching the regular expressions patterns to the + # ignore-list. The regex matches against paths and can be in Posix or Windows + # format. Because '\\' represents the directory delimiter on Windows systems, + # it can't be used as an escape character. + ignore-paths=.*/migrations + + # Files or directories matching the regular expression patterns are skipped. + # The regex matches against base names, not paths. The default value ignores + # Emacs file locks + ignore-patterns=^\.# + + # List of module names for which member attributes should not be checked + # (useful for modules/projects where namespaces are manipulated during runtime + # and thus existing member attributes cannot be deduced by static analysis). It + # supports qualified module names, as well as Unix pattern matching. + ignored-modules= + + # Python code to execute, usually for sys.path manipulation such as + # pygtk.require(). + #init-hook= + + # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the + # number of processors available to use, and will cap the count on Windows to + # avoid hangs. + jobs=1 + + # Control the amount of potential inferred values when inferring a single + # object. This can help the performance when dealing with large functions or + # complex, nested conditions. + limit-inference-results=100 + + # List of plugins (as comma separated values of python module names) to load, + # usually to register additional checkers. + load-plugins=pylint_django + + # Pickle collected data for later comparisons. + persistent=yes + + # Minimum Python version to use for version dependent checks. Will default to + # the version used to run pylint. + py-version=3.10 + + # Discover python modules and packages in the file system subtree. + recursive=no + + # Add paths to the list of the source roots. Supports globbing patterns. The + # source root is an absolute path or a path relative to the current working + # directory used to determine a package namespace for modules located under the + # source root. + source-roots= + + # When enabled, pylint would attempt to guess common misconfiguration and emit + # user-friendly hints instead of false-positive error messages. + suggestion-mode=yes + + # Allow loading of arbitrary C extensions. Extensions are imported into the + # active Python interpreter and may run arbitrary code. + unsafe-load-any-extension=no + + # In verbose mode, extra non-checker-related info will be displayed. + #verbose= + + + [BASIC] + + # Naming style matching correct argument names. + argument-naming-style=snake_case + + # Regular expression matching correct argument names. Overrides argument- + # naming-style. If left empty, argument names will be checked with the set + # naming style. + #argument-rgx= + + # Naming style matching correct attribute names. + attr-naming-style=snake_case + + # Regular expression matching correct attribute names. Overrides attr-naming- + # style. If left empty, attribute names will be checked with the set naming + # style. + #attr-rgx= + + # Bad variable names which should always be refused, separated by a comma. + bad-names=foo, + bar, + baz, + toto, + tutu, + tata + + # Bad variable names regexes, separated by a comma. If names match any regex, + # they will always be refused + bad-names-rgxs= + + # Naming style matching correct class attribute names. + class-attribute-naming-style=any + + # Regular expression matching correct class attribute names. Overrides class- + # attribute-naming-style. If left empty, class attribute names will be checked + # with the set naming style. + #class-attribute-rgx= + + # Naming style matching correct class constant names. + class-const-naming-style=UPPER_CASE + + # Regular expression matching correct class constant names. Overrides class- + # const-naming-style. If left empty, class constant names will be checked with + # the set naming style. + #class-const-rgx= + + # Naming style matching correct class names. + class-naming-style=PascalCase + + # Regular expression matching correct class names. Overrides class-naming- + # style. If left empty, class names will be checked with the set naming style. + #class-rgx= + + # Naming style matching correct constant names. + const-naming-style=UPPER_CASE + + # Regular expression matching correct constant names. Overrides const-naming- + # style. If left empty, constant names will be checked with the set naming + # style. + #const-rgx= + + # Minimum line length for functions/classes that require docstrings, shorter + # ones are exempt. + docstring-min-length=-1 + + # Naming style matching correct function names. + function-naming-style=snake_case + + # Regular expression matching correct function names. Overrides function- + # naming-style. If left empty, function names will be checked with the set + # naming style. + #function-rgx= + + # Good variable names which should always be accepted, separated by a comma. + good-names=i, + j, + k, + ex, + Run, + _ + + # Good variable names regexes, separated by a comma. If names match any regex, + # they will always be accepted + good-names-rgxs= + + # Include a hint for the correct naming format with invalid-name. + include-naming-hint=no + + # Naming style matching correct inline iteration names. + inlinevar-naming-style=any + + # Regular expression matching correct inline iteration names. Overrides + # inlinevar-naming-style. If left empty, inline iteration names will be checked + # with the set naming style. + #inlinevar-rgx= + + # Naming style matching correct method names. + method-naming-style=snake_case + + # Regular expression matching correct method names. Overrides method-naming- + # style. If left empty, method names will be checked with the set naming style. + #method-rgx= + + # Naming style matching correct module names. + module-naming-style=snake_case + + # Regular expression matching correct module names. Overrides module-naming- + # style. If left empty, module names will be checked with the set naming style. + #module-rgx= + + # Colon-delimited sets of names that determine each other's naming style when + # the name regexes allow several styles. + name-group= + + # Regular expression which should only match function or class names that do + # not require a docstring. + no-docstring-rgx=^_ + + # List of decorators that produce properties, such as abc.abstractproperty. Add + # to this list to register other decorators that produce valid properties. + # These decorators are taken in consideration only for invalid-name. + property-classes=abc.abstractproperty + + # Regular expression matching correct type alias names. If left empty, type + # alias names will be checked with the set naming style. + #typealias-rgx= + + # Regular expression matching correct type variable names. If left empty, type + # variable names will be checked with the set naming style. + #typevar-rgx= + + # Naming style matching correct variable names. + variable-naming-style=snake_case + + # Regular expression matching correct variable names. Overrides variable- + # naming-style. If left empty, variable names will be checked with the set + # naming style. + #variable-rgx= + + + [CLASSES] + + # Warn about protected attribute access inside special methods + check-protected-access-in-special-methods=no + + # List of method names used to declare (i.e. assign) instance attributes. + defining-attr-methods=__init__, + __new__, + setUp, + asyncSetUp, + __post_init__ + + # List of member names, which should be excluded from the protected access + # warning. + exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit + + # List of valid names for the first argument in a class method. + valid-classmethod-first-arg=cls + + # List of valid names for the first argument in a metaclass class method. + valid-metaclass-classmethod-first-arg=mcs + + + [DESIGN] + + # List of regular expressions of class ancestor names to ignore when counting + # public methods (see R0903) + exclude-too-few-public-methods= + + # List of qualified class names to ignore when counting class parents (see + # R0901) + ignored-parents= + + # Maximum number of arguments for function / method. + max-args=5 + + # Maximum number of attributes for a class (see R0902). + max-attributes=7 + + # Maximum number of boolean expressions in an if statement (see R0916). + max-bool-expr=5 + + # Maximum number of branch for function / method body. + max-branches=12 + + # Maximum number of locals for function / method body. + max-locals=15 + + # Maximum number of parents for a class (see R0901). + max-parents=7 + + # Maximum number of public methods for a class (see R0904). + max-public-methods=20 + + # Maximum number of return / yield for function / method body. + max-returns=6 + + # Maximum number of statements in function / method body. + max-statements=50 + + # Minimum number of public methods for a class (see R0903). + min-public-methods=2 + + + [EXCEPTIONS] + + # Exceptions that will emit a warning when caught. + overgeneral-exceptions=builtins.BaseException,builtins.Exception + + + [FORMAT] + + # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. + expected-line-ending-format= + + # Regexp for a line that is allowed to be longer than the limit. + ignore-long-lines=^\s*(# )??$ + + # Number of spaces of indent required inside a hanging or continued line. + indent-after-paren=4 + + # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 + # tab). + indent-string=' ' + + # Maximum number of characters on a single line. + max-line-length=100 + + # Maximum number of lines in a module. + max-module-lines=1000 + + # Allow the body of a class to be on the same line as the declaration if body + # contains single statement. + single-line-class-stmt=no + + # Allow the body of an if to be on the same line as the test if there is no + # else. + single-line-if-stmt=no + + + [IMPORTS] + + # List of modules that can be imported at any level, not just the top level + # one. + allow-any-import-level= + + # Allow explicit reexports by alias from a package __init__. + allow-reexport-from-package=no + + # Allow wildcard imports from modules that define __all__. + allow-wildcard-with-all=no + + # Deprecated modules which should not be used, separated by a comma. + deprecated-modules= + + # Output a graph (.gv or any supported image format) of external dependencies + # to the given file (report RP0402 must not be disabled). + ext-import-graph= + + # Output a graph (.gv or any supported image format) of all (i.e. internal and + # external) dependencies to the given file (report RP0402 must not be + # disabled). + import-graph= + + # Output a graph (.gv or any supported image format) of internal dependencies + # to the given file (report RP0402 must not be disabled). + int-import-graph= + + # Force import order to recognize a module as part of the standard + # compatibility libraries. + known-standard-library= + + # Force import order to recognize a module as part of a third party library. + known-third-party=enchant + + # Couples of modules and preferred modules, separated by a comma. + preferred-modules= + + + [LOGGING] + + # The type of string formatting that logging methods do. `old` means using % + # formatting, `new` is for `{}` formatting. + logging-format-style=old + + # Logging modules to check that the string format arguments are in logging + # function parameter format. + logging-modules=logging + + + [MESSAGES CONTROL] + + # Only show warnings with the listed confidence levels. Leave empty to show + # all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, + # UNDEFINED. + confidence=HIGH, + CONTROL_FLOW, + INFERENCE, + INFERENCE_FAILURE, + UNDEFINED + + # Disable the message, report, category or checker with the given id(s). You + # can either give multiple identifiers separated by comma (,) or put this + # option multiple times (only on the command line, not in the configuration + # file where it should appear only once). You can also use "--disable=all" to + # disable everything first and then re-enable specific checks. For example, if + # you want to run only the similarities checker, you can use "--disable=all + # --enable=similarities". If you want to run only the classes checker, but have + # no Warning level messages displayed, use "--disable=all --enable=classes + # --disable=W". + disable=raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero, + missing-module-docstring, + import-outside-toplevel, + fixme + + + # Enable the message, report, category or checker with the given id(s). You can + # either give multiple identifier separated by comma (,) or put this option + # multiple time (only on the command line, not in the configuration file where + # it should appear only once). See also the "--disable" option for examples. + enable= + + + [METHOD_ARGS] + + # List of qualified names (i.e., library.method) which require a timeout + # parameter e.g. 'requests.api.get,requests.api.post' + timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request + + + [MISCELLANEOUS] + + # List of note tags to take in consideration, separated by a comma. + notes=FIXME, + XXX, + TODO + + # Regular expression of note tags to take in consideration. + notes-rgx= + + + [REFACTORING] + + # Maximum number of nested blocks for function / method body + max-nested-blocks=5 + + # Complete name of functions that never returns. When checking for + # inconsistent-return-statements if a never returning function is called then + # it will be considered as an explicit return statement and no message will be + # printed. + never-returning-functions=sys.exit,argparse.parse_error + + + [REPORTS] + + # Python expression which should return a score less than or equal to 10. You + # have access to the variables 'fatal', 'error', 'warning', 'refactor', + # 'convention', and 'info' which contain the number of messages in each + # category, as well as 'statement' which is the total number of statements + # analyzed. This score is used by the global evaluation report (RP0004). + evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) + + # Template used to display messages. This is a python new-style format string + # used to format the message information. See doc for all details. + msg-template= + + # Set the output format. Available formats are: text, parseable, colorized, + # json2 (improved json format), json (old json format) and msvs (visual + # studio). You can also give a reporter class, e.g. + # mypackage.mymodule.MyReporterClass. + #output-format= + + # Tells whether to display a full report or only the messages. + reports=no + + # Activate the evaluation score. + score=yes + + + [SIMILARITIES] + + # Comments are removed from the similarity computation + ignore-comments=yes + + # Docstrings are removed from the similarity computation + ignore-docstrings=yes + + # Imports are removed from the similarity computation + ignore-imports=yes + + # Signatures are removed from the similarity computation + ignore-signatures=yes + + # Minimum lines number of a similarity. + min-similarity-lines=4 + + + [SPELLING] + + # Limits count of emitted suggestions for spelling mistakes. + max-spelling-suggestions=4 + + # Spelling dictionary name. No available dictionaries : You need to install + # both the python package and the system dependency for enchant to work. + spelling-dict= + + # List of comma separated words that should be considered directives if they + # appear at the beginning of a comment and should not be checked. + spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: + + # List of comma separated words that should not be checked. + spelling-ignore-words= + + # A path to a file that contains the private dictionary; one word per line. + spelling-private-dict-file= + + # Tells whether to store unknown words to the private dictionary (see the + # --spelling-private-dict-file option) instead of raising a message. + spelling-store-unknown-words=no + + + [STRING] + + # This flag controls whether inconsistent-quotes generates a warning when the + # character used as a quote delimiter is used inconsistently within a module. + check-quote-consistency=no + + # This flag controls whether the implicit-str-concat should generate a warning + # on implicit string concatenation in sequences defined over several lines. + check-str-concat-over-line-jumps=no + + + [TYPECHECK] + + # List of decorators that produce context managers, such as + # contextlib.contextmanager. Add to this list to register other decorators that + # produce valid context managers. + contextmanager-decorators=contextlib.contextmanager + + # List of members which are set dynamically and missed by pylint inference + # system, and so shouldn't trigger E1101 when accessed. Python regular + # expressions are accepted. + generated-members= + + # Tells whether to warn about missing members when the owner of the attribute + # is inferred to be None. + ignore-none=yes + + # This flag controls whether pylint should warn about no-member and similar + # checks whenever an opaque object is returned when inferring. The inference + # can return multiple potential results while evaluating a Python object, but + # some branches might not be evaluated, which results in partial inference. In + # that case, it might be useful to still emit no-member and other checks for + # the rest of the inferred objects. + ignore-on-opaque-inference=yes + + # List of symbolic message names to ignore for Mixin members. + ignored-checks-for-mixins=no-member, + not-async-context-manager, + not-context-manager, + attribute-defined-outside-init + + # List of class names for which member attributes should not be checked (useful + # for classes with dynamically set attributes). This supports the use of + # qualified names. + ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace + + # Show a hint with possible names when a member name was not found. The aspect + # of finding the hint is based on edit distance. + missing-member-hint=yes + + # The minimum edit distance a name should have in order to be considered a + # similar match for a missing member name. + missing-member-hint-distance=1 + + # The total number of similar names that should be taken in consideration when + # showing a hint for a missing member. + missing-member-max-choices=1 + + # Regex pattern to define which classes are considered mixins. + mixin-class-rgx=.*[Mm]ixin + + # List of decorators that change the signature of a decorated function. + signature-mutators= + + + [VARIABLES] + + # List of additional names supposed to be defined in builtins. Remember that + # you should avoid defining new builtins when possible. + additional-builtins= + + # Tells whether unused global variables should be treated as a violation. + allow-global-unused-variables=yes + + # List of names allowed to shadow builtins + allowed-redefined-builtins= + + # List of strings which can identify a callback function by name. A callback + # name must start or end with one of those strings. + callbacks=cb_, + _cb + + # A regular expression matching the name of dummy variables (i.e. expected to + # not be used). + dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + + # Argument names that match this expression will be ignored. + ignored-argument-names=_.*|^ignored_|^unused_ + + # Tells whether we should check for unused import in __init__ files. + init-import=no + + # List of qualified module names which can have objects that can redefine + # builtins. + redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + + # pylint_django configuration + [pylint-django] + django-settings-module=.settings + ``` + +- Run pylint for code quality checks + + ```sh + pylint **/*.py + ``` + +- Install VS Code pylint extension [`ms-python.pylint`](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint) + +13. Setup pre commit + +- Install pre commit package + + ```sh + pip install pre_commit + ``` + +- Add installed pre commit package to requirements file + + ```sh + pip freeze | grep pre_commit >> requirements.txt + ``` + +- Add pre commit config file `.pre-commit-config.yaml` + + ```yaml + repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + ``` + +- Add pre commit config for black in `.pre-commit-config.yaml` + + ```yaml + repos: + - repo: https://github.com/psf/black + rev: 25.1.0 + hooks: + - id: black + name: black to format python code + ``` + +- Add pre commit config for isort in `.pre-commit-config.yaml` + + ```yaml + repos: + - repo: https://github.com/pycqa/isort + rev: 6.0.1 + hooks: + - id: isort + name: isort to sort imports + args: + - --profile + - black + - --verbose + - --skip-glob + - "**/migrations/*.py" + ``` + +- Add pre commit config for mypy in `.pre-commit-config.yaml` + + ```yaml + repos: + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.17.0 + hooks: + - id: mypy + name: mypy to check types + additional_dependencies: + - django-jazzmin==3.0.1 + - django-stubs==5.2.2 + - djangorestframework==3.16.0 + - djangorestframework-stubs==3.16.1 + args: ["--config-file=mypy.ini"] + ``` + +- Add pre commit config for pylint in `.pre-commit-config.yaml` + + ```yaml + repos: + - repo: https://github.com/pycqa/pylint + rev: v3.3.7 + hooks: + - id: pylint + name: pylint to check code quality + entry: pylint + language: python + types: [python] + args: ["--rcfile=.pylintrc"] + additional_dependencies: + - django-jazzmin==3.0.1 + - Django==5.2.4 + - pylint-django==2.6.1 + - djangorestframework==3.16.0 + ``` + +- Install pre commit dependencies + + ```sh + pre-commit install + ``` + +- Run pre-commit hooks manually + + ```sh + pre-commit run --all-files + ``` + +- Note:- pre commit official [doc](https://pre-commit.com/) + +14. Setup pre push hook + +- for linux or macos + + ```sh + cp .githooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push + ``` + +- for windowns + + ```sh + copy .githooks\pre-push .git\hooks\pre-push + ``` + +15. Setup VS Code test runner + +- Add manage.py path variable in `.env` file + + ```env + MANAGE_PY_PATH=manage.py + ``` + +- Configure VS Code to for test runner in `.vscode/settings.json` + + ```json + { + "python.testing.unittestEnabled": true, + "python.testing.pytestEnabled": false, + "python.testing.unittestArgs": ["-p", "*test*.py"] + } + ``` + +16. Install recommended VS Code extensions + +- Open the extensions sidebar in VS Code `ctrl+shift+x` or `cmd+shift+x` + +- Type @recommended in the search bar + +- Install the recommended extensions diff --git a/django_starter/django_starter/__init__.py b/backend/__init__.py similarity index 100% rename from django_starter/django_starter/__init__.py rename to backend/__init__.py diff --git a/django_starter/django_starter/asgi.py b/backend/asgi.py similarity index 56% rename from django_starter/django_starter/asgi.py rename to backend/asgi.py index 263c45a..ecaff6f 100644 --- a/django_starter/django_starter/asgi.py +++ b/backend/asgi.py @@ -1,16 +1,16 @@ """ -ASGI config for django_starter project. +ASGI config for backend project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/ """ import os from django.core.asgi import get_asgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_starter.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings") application = get_asgi_application() diff --git a/django_starter/django_starter/settings.py b/backend/settings.py similarity index 73% rename from django_starter/django_starter/settings.py rename to backend/settings.py index ac26394..ee1598e 100644 --- a/django_starter/django_starter/settings.py +++ b/backend/settings.py @@ -1,32 +1,31 @@ """ -Django settings for django_starter project. +Django settings for backend project. -Generated by 'django-admin startproject' using Django 4.1.4. +Generated by 'django-admin startproject' using Django 5.2.4. For more information on this file, see -https://docs.djangoproject.com/en/4.1/topics/settings/ +https://docs.djangoproject.com/en/5.2/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.1/ref/settings/ +https://docs.djangoproject.com/en/5.2/ref/settings/ """ from pathlib import Path -from typing import List # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure-122)h3o=1ewbz!3)e^b1n3h*i*on3(-v$%8**r&n--0t2sijcn" +SECRET_KEY = "django-insecure-2l@ji^toi5&60%f!if3-9bkx1y(f)f+*1vs0(q3l2y1-&i4jv%" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS: List[str] = [] +ALLOWED_HOSTSS: list[str] = [] # Application definition @@ -38,6 +37,8 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "rest_framework", + "core", ] MIDDLEWARE = [ @@ -50,7 +51,7 @@ "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = "django_starter.urls" +ROOT_URLCONF = "backend.urls" TEMPLATES = [ { @@ -59,7 +60,6 @@ "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", @@ -68,11 +68,11 @@ }, ] -WSGI_APPLICATION = "django_starter.wsgi.application" +WSGI_APPLICATION = "backend.wsgi.application" # Database -# https://docs.djangoproject.com/en/4.1/ref/settings/#databases +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases DATABASES = { "default": { @@ -83,7 +83,7 @@ # Password validation -# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -102,7 +102,7 @@ # Internationalization -# https://docs.djangoproject.com/en/4.1/topics/i18n/ +# https://docs.djangoproject.com/en/5.2/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -114,11 +114,11 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.1/howto/static-files/ +# https://docs.djangoproject.com/en/5.2/howto/static-files/ STATIC_URL = "static/" # Default primary key field type -# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/django_starter/django_starter/urls.py b/backend/urls.py similarity index 82% rename from django_starter/django_starter/urls.py rename to backend/urls.py index 1a80484..ec9924b 100644 --- a/django_starter/django_starter/urls.py +++ b/backend/urls.py @@ -1,7 +1,8 @@ -"""django_starter URL Configuration +""" +URL configuration for backend project. The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.1/topics/http/urls/ + https://docs.djangoproject.com/en/5.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -13,8 +14,9 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + from django.contrib import admin -from django.urls import include, path +from django.urls import path urlpatterns = [ path("admin/", admin.site.urls), diff --git a/django_starter/django_starter/wsgi.py b/backend/wsgi.py similarity index 56% rename from django_starter/django_starter/wsgi.py rename to backend/wsgi.py index 158b332..2e99f5a 100644 --- a/django_starter/django_starter/wsgi.py +++ b/backend/wsgi.py @@ -1,16 +1,16 @@ """ -WSGI config for django_starter project. +WSGI config for backend project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_starter.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings") application = get_wsgi_application() diff --git a/django_starter/db.sqlite3 b/core/__init__.py similarity index 100% rename from django_starter/db.sqlite3 rename to core/__init__.py diff --git a/core/admin.py b/core/admin.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps.py b/core/apps.py new file mode 100644 index 0000000..cd57cce --- /dev/null +++ b/core/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + """Core app config""" + + default_auto_field = "django.db.models.BigAutoField" + name = "core" diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..2df654b --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,29 @@ +# Generated by Django 5.2.4 on 2025-08-14 07:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Student", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("first_name", models.CharField(max_length=30)), + ("last_name", models.CharField(max_length=30)), + ], + ), + ] diff --git a/core/migrations/__init__.py b/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/models.py b/core/models.py new file mode 100644 index 0000000..5466fff --- /dev/null +++ b/core/models.py @@ -0,0 +1,15 @@ +from django.db import models + +# Create your models here. + + +class Student(models.Model): + """Student Model""" + + first_name = models.CharField(max_length=30) + last_name = models.CharField(max_length=30) + + def __str__(self): + """Student string representation""" + + return f"{self.first_name} {self.last_name}" diff --git a/core/tests.py b/core/tests.py new file mode 100644 index 0000000..55f4993 --- /dev/null +++ b/core/tests.py @@ -0,0 +1,26 @@ +from django.test import TestCase + +from .models import Student + +# Create your tests here. + + +class StudentModelTest(TestCase): + """Student model test""" + + def setUp(self): + self.student = Student.objects.create( + first_name="John", + last_name="Doe", + ) + + def test_student_creation(self): + """Test that a student instance is created correctly.""" + + self.assertEqual(self.student.first_name, "John") + self.assertEqual(self.student.last_name, "Doe") + + def test_str_method(self): + """Test the __str__ method of the Student model.""" + + self.assertEqual(str(self.student), "John Doe") diff --git a/core/views.py b/core/views.py new file mode 100644 index 0000000..e69de29 diff --git a/isort.cfg b/isort.cfg new file mode 100644 index 0000000..b678189 --- /dev/null +++ b/isort.cfg @@ -0,0 +1,4 @@ +[settings] +profile = black +verbose = true +skip_glob = **/migrations/*.py diff --git a/django_starter/manage.py b/manage.py old mode 100644 new mode 100755 similarity index 88% rename from django_starter/manage.py rename to manage.py index ea424a9..1917e46 --- a/django_starter/manage.py +++ b/manage.py @@ -6,7 +6,7 @@ def main(): """Run administrative tasks.""" - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_starter.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/mypy.ini b/mypy.ini index 81de0b4..2693036 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,6 +1,6 @@ [mypy] -mypy_path = ./django_starter plugins = mypy_django_plugin.main +exclude = migrations|tests [mypy.plugins.django-stubs] -django_settings_module = "django_starter.settings" \ No newline at end of file +django_settings_module = "backend.settings" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..5bbddd5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,2 @@ +[tool.black] +force-exclude = "/migrations/" diff --git a/requirements.txt b/requirements.txt index 332d1f4..80b0424 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,11 @@ -black==22.12.0 -Django==4.1.4 -django-stubs==1.13.1 -isort==5.11.3 -mypy==0.991 -pylint==2.15.9 -pylint-django==2.5.3 \ No newline at end of file +Django==5.2.4 +djangorestframework==3.16.0 +coverage==7.9.2 +mypy==1.17.0 +django-stubs==5.2.2 +djangorestframework-stubs==3.16.1 +black==25.1.0 +isort==6.0.1 +pylint==3.3.7 +pylint-django==2.6.1 +pre_commit==4.2.0