# Django course Project github: ## Summary * [get & post](#Get-amp-Post) * [blocking, pop-up message: before sending, you need save data](#Pop-Up-message-need-to-save) * [paginations in classes (ListView)](#Pagination-in-ListView) * [separate update and search form](#Separate-Form) * [mixins, load data from excel](#Mixins) * [GitHub, basic using and ?multiuser mode?](#Git) * [databases](#Databases) * [Docker](#Docker) ___ ## Themes ### Get & Post ##### In function ```python= def function_view(request): if request.method != "POST" raise HttpResponseNotAllowed("Method not allowed") # Do anything return HttpResponse("Some response") ``` *`request.method` maybe:* * `GET` - getting data * `POST` - add new data * `PATCH` - spot update * `PUT` - full update * `DELETE` - remove obj * `HEAD` - get metainfo (such as headers, status, cookies) from get method *[Need use JS](https://jsfiddle.net/q9k54v1u/63/)* ##### In view class ```python= class SomeView(View): def get(self, request, *args, **kwargs): data = request.GET # https://some-site/path?first=1&second=2, # QueryDict with first=1 and second=2 param_age = data.get("s_age") if isinstance(param_age, int): age = int(param_age) else: raise HttpResponseBadRequest("Param age must be integer") # Do anything return HttpResponse("Some response") def post(self, request, *args, **kwargs): data = request.POST # Do anything return HttpResponse("Some response") def head(self, ...): pass # Your may add other methods, look above ``` #### Get POST data from get_context_data or get_queryset methods in ListView ```python= class SomeListView(ListView): def post(self, *args, **kwargs): # Off HttpResponseNotAllowed errir return super().get(*args, **kwargs) def get_queryset(self): post_data = self.request.POST # Do anything return SomeModel.objects.all() ``` ### Pagination in ListView ###### some_app/views.py ```python= class SomeListView(ListView): model = Some # Some is Model paginate_by = 2 # Count of items per page # Default context_object_name eq. "some_list" # as model name + _list # Default template_name eq. some_list.html # as model name + _list.html ``` ###### templates/some_app/some_list.html *Links on previos page next page and list pages* ```htmlmixed= <!-- regular list --> <ul class="some-list"> {% for some in some_list %} <li>{{ some.some_field }}</li> {% endfor %} </ul> <!-- end regular list --> <!-- paginator --> <ul class="paginator"> {% if page_obj.has_other_pages %} {% if page_obj.has_previous %} <li class="page-item"> <a class="page-link" href="?page={{ page_obj.previous_page_number }}" >Пред.</a> </li> {% endif %} {% for p in page_obj.paginator.page_range %} {% if page_obj.number == p %} <li class="page-item active" aria-current="page" ><a class="page-link" href="?page={{ p }}" >{{ p }}<span class="sr-only"></span></a> </li> {% elif p > page_obj.number|add:-5 and p < page_obj.number|add:5 %} <li class="page-item"> <a class="page-link" href="?page={{ p }}" >{{ p }}</a> </li> {% endif %} {% endfor %} {% if page_obj.has_next %} <li class="page-item"> <a class="page-link" href="?page={{ page_obj.next_page_number }}" >След.</a> </li> {% endif %} {% else %} Эта страница единственная {% endif %} </ul> <!-- end paginator --> ``` ### Git > global information tracker, version control system designed to handle everything from small to very large projects with speed and efficiency. * SignUp * Create ssh cert & upload public to GitHub * `ssh-keygen -t rsa -b 4096 -C "your@mail.com"` * Paste this public key `cat .ssh/id_rsa.pub` to [GitHub ssh keys](https://github.com/settings/ssh/new) * Create repo * Prepare code to using git * Linter such as `black` * Create `requirements.txt` * Create some description README.md ([MarkDown ref](https://htmlacademy.ru/blog/articles/markdown)) * Maybe `.env` * Install git ([windows](https://github.com/git-for-windows/git/releases/download/v2.36.1.windows.1/Git-2.36.1-64-bit.exe), [linux](https://git-scm.com/download/linux)) * Git basic using * *if need*, basic using terminal ( `cd`, `ls`, `rm`, `mv` ) * `git help` & `git help COMMAND( ex. remote )` * Setup git: `git config --global KEY VALUE` - `init.defaultBranch` - default branch, `master` or `main` - `user.name` - user name - `user.email` - user email - `pull.ff only` - no rebase on pull * `git init` ( `-b master_branch` ) * file .gitignore, autogenerator [gitignore.io](https://gitignore.io) * `remote` ( `add` | `remove` | `get-url` | `set-url` | `rename` ) save local changes * `git status` * `git add` ( `.` | `-a` | `./README.md` ) * `git commit` ( `-m "message"` | `-am "message"` ) * `git rm` ( `-r .` | `./file` ) * `git rebase branch` * `git branch` ( `-a` | `-D old_branch` | `-M renamed_branch` | `-C copied_branch` ) * `git log` * `git reset HEAD~1` * `git checkout` ( `-- .` | `-b new_branch` | `some_branch` ) * `git push remote branch` ( `--set-upstream` ) upload to remote repo code * `git pull remote branch` ( `--set-upstream` ) get commits from remote * `git clone git://github.com/user/repo.git dir` ### Databases #### Intro, connection to another db ##### Example configs for MS SQL *Be later* ##### Example configs for MySQL ```python= DATABASES = { "some_database": { "ENGINE": "django.db.backends.mysql", "NAME": "some_database", "USER": "root", "PASSWORD": "your_password", "HOST": "127.0.0.1", "PORT": "3306", } } ``` Install client: `pip install mysqlclient` ##### Example configs for PostgreSQL ```python= DATABASES = { "some_database": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "some_database", "USER": "root", "PASSWORD": "your_password", "HOST": "127.0.0.1", "PORT": "3306", } } 'ENGINE': '', ``` Install client: `pip install psycopg2` #### Some databases Using for: * replications * sharing tables #### Example replications > Need using `replicas` for read and `primary` for write ###### app/settings.py ```python= DATABASES = { 'default': {}, 'primary': { # some configs }, 'replica1': { # some configs }, 'replica2': { # some configs }, ... } DATABASE_ROUTERS = ['app.databases.ReplicationRouter'] ``` ###### app/databases.py ```python= class ReplicationRouter: def db_for_read(self, model, **hints): return random.choice(['replica1', 'replica2']) # Maybe add complex control based on response time or anything def db_for_write(self, model, **hints): # In replication mode, write occurs only in primary database return 'primary' def allow_relation(self, obj1, obj2, **hints): # Relation with tables: foregn key and other db_set = {'primary', 'replica1', 'replica2'} if obj1._state.db in db_set and obj2._state.db in db_set: return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): # For makemigrations and search errors return True ``` #### Sharing tables ###### app/settings.py ```python= DATABASES = { 'default': { # Some configs }, 'other_db': { # Some configs } } DATABASE_ROUTERS = ['app.databases.AuthRouter'] ``` ###### app/databases.py ```python= class OtherRouter: route_app_labels = {'other', 'contenttypes'} def db_for_read(self, model, **hints): if model._meta.app_label in self.route_app_labels: return 'other_db' return None def db_for_write(self, model, **hints): if model._meta.app_label in self.route_app_labels: return 'other_db' return None def allow_relation(self, obj1, obj2, **hints): if ( obj1._meta.app_label in self.route_app_labels or obj2._meta.app_label in self.route_app_labels ): return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label in self.route_app_labels: return db == 'other_db' return None ``` ### Docker > Docker -- это открытая платформа для разработки, доставки и запуска приложений. Docker позволяет вам отделить ваши приложения от вашей инфраструктуры, чтобы вы могли быстро доставлять программное обеспечение. С помощью Docker вы можете управлять своей инфраструктурой так же, как вы управляете своими приложениями. Воспользовавшись методологиями Docker для быстрой доставки, тестирования и развертывания кода, вы можете значительно сократить задержку между написанием кода и его запуском в рабочей среде. ![Docker system](https://docs.docker.com/engine/images/architecture.svg) #### Установка [Windows](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe) *Может потребоваться установка WSL2* ##### Command: run > Run docker container ```shell= docker run -it ubuntu /bin/bash ``` Where: * `-i` -- interactive mode * `-t` -- tty mode, attach to terminal * `ubuntu` -- image name * `/bin/bash` -- runned command Other params: * `--volume` or `-v` ( `name_volume_or_host_path:/path/in/container:other,params` ) * `--mount` params one line, splitted `,` * `type=`: * `volume` -- virtual * `bind` -- some host folder or file * `tmpfs` -- in memory * `src=`, optional: `./local/path` * `dst=` | `target=`: `/container/path` * `volume-opt` -- other params * `readonly`, optional * `--secret source=some_secret,target=name_secret,mode=0400` * `-p 9000:1000`, `9000` -- host port, `1000` -- container host * `-e name:value` -- enviroment variable ##### Some commands * `ps` - list runned containers * `-a` - all containers * `stats` -- resource usage * `inspect some-container` -- get info about container or image * `exec CONTAINER COMMAND` -- run command in container * `-it` -- interactive mode * `-d` -- detached * `logs some-container` ( `-f` | `--tail 10` ) * `pause some-container` * `restart some-container` * `stop some-container` * `cp` -- copy from host to container and opposite * ex.: `container:/some/path ./host/path` * ex.: `./host/path container:/some/path` * `rm some-container` * `rmi some-image` * `top` as base linux `top` * `kill some-container` * `attach some-container` ##### volume ![image](https://docs.docker.com/storage/images/types-of-mounts-volume.png) Create volume: `create new-volume` List volume: `ls` Info: `inspect some-volume` Remove: `rm some-volume` ###### Example ```shell= docker run -d \ --name devtest \ --mount source=myvol2,target=/app \ nginx:latest ``` ##### secret before: `docker swarm init` * `create` * ex.: `secret create file-secret some-file.txt` * ex.: `secret create str-secret some-secret-string` * `ls` -- get list of secrets * `rm file-secret` -- remove secret * `inspect file-secret` -- get info ```shell= docker service create \ --name wordpress \ --secret source=some-secret,target=some-secret,mode=0400 \ --secret source=another-secret,target=/some-path/some-secret,mode=0400 \ nginx:latest ``` #### Create image ```dockerfile= FROM python:alpine as builder WORKDIR /app ADD requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD python manage.py runserver ``` Build container: `docker build --tag dj-image .` Some commands * `docker images` -- list images * `docker image` * `prune` -- remove unused images * `rm` -- remove * `ls` -- list ## Docker-Compose ###### File: docker-compose.yml ```yaml= services: api: build: context: . dockerfile: Dockerfile depends_on: - db restart: always volumes: - "./host:./container" ports: - "9000:2111" links: - "db:some-db" db: image: mcr.microsoft.com/mssql/server volumes: environment: ACCEPT_EULA: "Y" SA_PASSWORD: "password" ```