Схема (schema) в базе данных — это логическая группировка объектов (таблиц, индексов, представлений и т. д.) внутри одной БД.
Схема — это контейнер для объектов БД (таблиц, индексов, процедур).
База данных (company_db)
├── Схема: public (по умолчанию)
│ ├── Таблица: employees
│ ├── Таблица: departments
├── Схема: hr
│ ├── Таблица: employees
│ ├── Таблица: salaries
├── Схема: sales
│ ├── Таблица: customers
│ ├── Таблица: orders
Создание схемы (
CREATE SCHEMA
) CREATE SCHEMA hr; -- Создаём схему "hr"
Создание таблицы внутри схемы
CREATE TABLE hr.employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
position VARCHAR(50)
);
Выбор схемы по умолчанию
SET search_path TO hr;
Если в БД хранятся разные области бизнеса (кадры, продажи, финансы), их можно разделить по схемам:
-
hr.employees
, hr.salaries
-
sales.orders
, sales.customers
Например, в PostgreSQL можно создать схему
dev
для тестов: -
dev.users
— тестовая версия таблицы -
prod.users
— продакшен-версия Можно дать доступ к разным схемам разным пользователям:
GRANT USAGE ON SCHEMA hr TO hr_manager;
GRANT SELECT ON ALL TABLES IN SCHEMA hr TO hr_manager;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2
SSL (Secure Sockets Layer) и TLS (Transport Layer Security) — это криптографические протоколы, которые обеспечивают защищённую передачу данных по сети.
SSL — это более старая версия, которая больше не используется из-за уязвимостей.
TLS — это современный и надёжный протокол, который обеспечивает шифрование, целостность и аутентификацию при передаче данных.
Именно благодаря TLS сайты работают по защищённому протоколу HTTPS.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1🤔1💊1
Когда пользователь отправляет HTTP-запрос (например, открывает страницу сайта), Django проходит несколько этапов обработки, прежде чем вернуть ответ.
Когда клиент (браузер, API) отправляет запрос, его принимает WSGI/ASGI-сервер (
Gunicorn
, Daphne
). Если проект синхронный → работает через WSGI (
wsgi.py
). Если проект асинхронный → через ASGI (
asgi.py
). GET /hello/ HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Django превращает HTTP-запрос в объект
HttpRequest
, который передаётся в view
. def my_view(request):
print(request.method) # 'GET'
print(request.path) # '/hello/'
print(request.GET) # {'name': 'Alice'}
Прежде чем запрос дойдёт до
view
, Django проходит через мидлвари, которые могут: Проверять авторизацию (
AuthenticationMiddleware
). Защищать от CSRF (
CsrfViewMiddleware
). Перенаправлять запросы (
CommonMiddleware
). MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
]
Django ищет, какая функция (
view
) должна обработать этот URL. from django.urls import path
from myapp.views import hello_view
urlpatterns = [
path("hello/", hello_view), # Запрос "/hello/" попадёт в hello_view
]
Когда Django находит подходящее представление (
view
), оно вызывается. from django.http import HttpResponse
def hello_view(request):
return HttpResponse("Привет, мир!")
Django берёт
HttpResponse
и передаёт его обратно через middleware
(например, сжатие, защита, заголовки безопасности). HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12
Привет, мир!
На последнем этапе WSGI/ASGI-сервер отправляет ответ обратно браузеру или API-клиенту.
Клиент (браузер) → WSGI/ASGI → Django Middleware → URL Dispatcher → View → Response → Клиент
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
wait() похожа на gather, но предоставляет более гибкий контроль, позволяя:
- ждать завершения всех задач;
- ждать первых завершённых;
- получить информацию о выполненных и ожидающих задачах.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7💊1
В Python все данные делятся на изменяемые (mutable) и неизменяемые (immutable)
После создания их нельзя изменить!
x = 10
print(id(x)) # 140735598722544 (адрес в памяти)
x = x + 5 # Создаётся новый объект!
print(id(x)) # 140735598722704 (новый адрес)
Пример:
str
неизменяемая s = "hello"
print(id(s)) # 140735598723664
s = s + " world" # Создаётся новая строка!
print(id(s)) # 140735598724240 (новый адрес)
Можно менять их содержимое без создания нового объекта.
lst = [1, 2, 3]
print(id(lst)) # 140735598722544
lst.append(4) # Изменяем список
print(id(lst)) # 140735598722544 (адрес остался тот же!)
Пример:
dict
изменяемый d = {"name": "Alice"}
print(id(d)) # 140735598723664
d["age"] = 25 # Добавляем ключ
print(id(d)) # 140735598723664 (адрес не изменился!)
Неизменяемые объекты безопаснее для ключей
dict
и set
d = {}
d[[1, 2, 3]] = "Ошибка!" # ❌ TypeError: unhashable type: 'list'
Используем
tuple
вместо list
(он неизменяемый) d[(1, 2, 3)] = "OK"
Ошибки с изменяемыми значениями по умолчанию
def add_item(lst=[]): # ❌ Опасный код!
lst.append(1)
return lst
print(add_item()) # [1]
print(add_item()) # [1, 1] ❌ Список не создаётся заново!
Используем
None
вместо списка def add_item(lst=None):
if lst is None:
lst = []
lst.append(1)
return lst
copy()
делает поверхностную копию (новый объект, но старые вложенные элементы). deepcopy()
делает глубокую копию (всё новое). import copy
lst1 = [[1, 2, 3], [4, 5, 6]]
lst2 = copy.copy(lst1) # Поверхностная копия
lst2[0][0] = 99
print(lst1) # [[99, 2, 3], [4, 5, 6]] ❌ Исходный список изменился!
Используем
deepcopy()
для полной независимой копии lst3 = copy.deepcopy(lst1)
lst3[0][0] = 100
print(lst1) # [[99, 2, 3], [4, 5, 6]] ✅ Не изменился!
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Это подход к проектированию веб-сервисов, основанный на архитектурном стиле REST (*Representational State Transfer*). Это не протокол или стандарт, а набор принципов и ограничений, которые используются для создания систем, взаимодействующих через HTTP. Если API соответствует этим принципам, его называют RESTful.
Клиент (например, браузер или мобильное приложение) и сервер (где размещена база данных и логика обработки данных) чётко разделены:
Клиент запрашивает данные или отправляет запросы к серверу.
Сервер отвечает, предоставляя ресурсы или выполняя действия.
Каждый запрос от клиента к серверу должен быть самодостаточным. Это означает, что сервер не хранит информацию о состоянии клиента между запросами. Вся необходимая информация передается в запросе (например, токен аутентификации).
RESTful API использует единый, стандартный интерфейс для взаимодействия. Это достигается следующими средствами:
Идентификация ресурсов через URI: Каждый ресурс имеет уникальный адрес (URI).
GET https://api.example.com/users/123
Использование стандартных HTTP-методов:
GET — для получения данных.
POST — для создания новых данных.
PUT или PATCH — для обновления данных.
DELETE — для удаления данных.
Ресурсы как представления: Ресурсы передаются в формате JSON, XML или другом формате.
Ответы сервера могут быть кэшируемыми. Это уменьшает нагрузку на сервер и ускоряет работу клиента.
RESTful системы могут включать несколько слоев (например, балансировщики нагрузки, кеш-сервисы), но клиент взаимодействует только с сервером, не зная о внутренних слоях.
Иногда сервер может передавать исполняемый код (например, JavaScript) клиенту, чтобы расширить его функциональность. Это не обязательно.
RESTful архитектура позволяет:
Клиенты легко понимают, как обращаться к ресурсам (используя стандартные методы и адреса).
Клиенты и серверы могут развиваться независимо друг от друга.
RESTful API легко масштабируются, так как все запросы независимы друг от друга (статичность).
RESTful API поддерживают стандартизированные протоколы (HTTP), что делает интеграцию с другими сервисами проще.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
На практике применяются такие декораторы:
-
-
-
-
-
- Декораторы логирования, валидации, измерения времени выполнения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
В Python пакетирование библиотек — это процесс создания, распространения и установки пакетов (модулей) с кодом. Это позволяет разработчикам легко устанавливать и переиспользовать чужие библиотеки.
Пакет — это набор модулей, объединенных в одну структуру (обычно это папка с файлом
__init__.py
). mypackage/
│── mymodule.py
│── __init__.py
└── utils.py
Допустим, у нас есть пакет
mypackage
, в котором есть функция say_hello()
. Структура проекта
mypackage/
│── mymodule.py
│── __init__.py
└── setup.py
Файл
mypackage/mymodule.py
def say_hello():
return "Привет, мир!"
Файл
mypackage/__init__.py
(он делает папку пакетом)from .mymodule import say_hello
Теперь можно использовать
mypackage
в кодеimport mypackage
print(mypackage.say_hello()) # Выведет: Привет, мир!
Чтобы установить готовую библиотеку из PyPI, используем
pip
pip install requests # Установка библиотеки requests
Чтобы посмотреть установленные пакеты
pip list
Чтобы удалить пакет
pip uninstall requests
Чтобы обновить пакет
pip install requests --upgrade
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
- Оба предоставляют компактный синтаксис для создания объектов с полями.
- Поддерживают доступ по имени (obj.field).
- Иммутабельность (frozen=True для dataclass, по умолчанию в namedtuple).
Отличия:
- namedtuple — неизменяемый, лёгкий и быстрый, но не поддерживает методы, наследование и типизацию так же гибко.
- dataclass — более гибкий, позволяет использовать методы, наследование, значения по умолчанию, валидацию и другие параметры (frozen, order, repr, init и т.д.).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2
Это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать предыдущее состояние объекта без нарушения инкапсуляции. Этот паттерн особенно полезен для реализации операций отмены и повтора, так как он позволяет хранить состояния объектов и возвращать их к этим состояниям по необходимости.
Позволяет сохранять текущее состояние объекта и восстанавливать его позже.
Обеспечивает сохранение состояния объекта без нарушения его инкапсуляции. Внутренние детали объекта остаются скрытыми от других объектов.
Поддерживает функциональность отмены и повтора операций, так как позволяет возвращать объект к предыдущим состояниям.
Пример реализации
class Memento:
def __init__(self, state: str):
self._state = state
def get_state(self) -> str:
return self._state
class TextEditor:
def __init__(self):
self._state = ""
self._history = []
def type(self, text: str):
self._save_state()
self._state += text
def _save_state(self):
self._history.append(Memento(self._state))
def undo(self):
if not self._history:
return
memento = self._history.pop()
self._state = memento.get_state()
def get_content(self) -> str:
return self._state
# Клиентский код для использования паттерна Хранитель
def main():
editor = TextEditor()
editor.type("Hello, ")
editor.type("world!")
print(editor.get_content()) # Hello, world!
editor.undo()
print(editor.get_content()) # Hello,
editor.undo()
print(editor.get_content()) #
if __name__ == "__main__":
main()
Сохраняет состояние объекта. Он предоставляет методы для получения сохраненного состояния, но не предоставляет методов для изменения состояния, что обеспечивает неизменность.
Создает и использует объекты
Memento
для сохранения и восстановления своего состояния. Методы type
и undo
позволяют редактировать текст и отменять изменения.Сохраняет текущее состояние редактора в истории перед каждым изменением.
Восстанавливает предыдущее состояние редактора из истории.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Предупреждения — это сообщения о потенциальных проблемах, которые не прерывают выполнение. Их можно создать с помощью модуля warnings и вызвать через warn().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Django использует
sqlparse
и asgiref
как вспомогательные библиотеки для работы с SQL и асинхронностью. Разберём их назначение подробно. sqlparse
(SQL Parser) — это библиотека для анализа, форматирования и обработки SQL-запросов. В Django она используется в админке, логах и отладке ORM. Форматирование SQL-запросов в
django.db.connection.queries
from django.db import connection
from sqlparse import format
queries = connection.queries # Получаем список SQL-запросов
for q in queries:
print(format(q["sql"], reindent=True, keyword_case="upper")) # Красивый SQL
Логирование SQL-запросов
sqlparse
помогает Django красиво выводить SQL-запросы в DEBUG=True
.Команда
sqlmigrate
python manage.py sqlmigrate app_name 0001
asgiref
(Asynchronous Server Gateway Interface Reference) — это библиотека, которая помогает Django работать в асинхронном (async) режиме. Django поддерживает ASGI с версии 3.0, и asgiref
— это её обязательная зависимость.Django с версии 3.0 поддерживает асинхронные вьюхи, WebSockets и асинхронные базы данных (например, с
asyncpg
).В
settings.py
есть параметр:ASGI_APPLICATION = "myproject.asgi.application"
Django 4.x поддерживает асинхронные middleware через
asgiref.sync
и asgiref.local
.Django использует
sync_to_async()
и async_to_sync()
из asgiref
:from asgiref.sync import sync_to_async
def sync_function():
return "Hello from sync!"
async_function = sync_to_async(sync_function)
print(async_function()) # Вызывает синхронную функцию в асинхронном коде
Позволяет хранить данные отдельно для каждого потока или запроса.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Квадратные скобки создают список, а круглые — генератор. Список сразу хранит все значения в памяти, генератор же отдаёт элементы по одному при необходимости, экономя ресурсы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥8💊1
В HTTP коды состояния указывают, как сервер обработал запрос. Они делятся на 5 категорий:
1xx (Информационные – запрос принят, продолжаем.
2xx (Успешные) – всё хорошо.
3xx (Перенаправления) – запрашиваемый ресурс перемещён.
4xx (Ошибки клиента) – клиент отправил неправильный запрос.
5xx (Ошибки сервера) – сервер не смог обработать запрос.
4xx:
400: Проверить формат запроса.
401: Убедиться, что пользователь авторизован.
403: Проверить права доступа.
404: Убедиться, что URL правильный.
5xx:
500: Проверить код сервера (ошибки в логах).
502/504: Проверить настройки Nginx/Proxy.
503: Сервер перегружен → добавить балансировку нагрузки.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
1. DNS-запрос — доменное имя (например,
2. Установка соединения — браузер открывает TCP-соединение с сервером, часто с использованием HTTPS (т.е. через TLS).
3. Отправка HTTP-запроса — браузер отправляет, например, GET /, чтобы получить главную страницу.
4. Обработка на сервере — сервер принимает запрос, обрабатывает его и формирует ответ.
5. Получение ответа — браузер получает HTML-страницу, начинает загружать CSS, JS, изображения и прочее.
6. Рендеринг страницы — браузер строит DOM и отображает контент пользователю.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8💊3
Когда в проекте много файлов, могут возникать конфликты импортов. Python ищет модули в определённом порядке, и если несколько файлов имеют одинаковые имена или неправильные пути, может возникнуть ошибка.
Вместо
import mymodule # Может вызвать конфликт, если есть несколько файлов с таким именем
Лучше указывать полный путь в пакетах
from myproject.utils.mymodule import my_function
Если у вас есть файл
math.py
, импорт import math
будет загружать ваш файл, а не стандартный модуль math
из Python. - Не называйте файлы именами стандартных модулей:
math.py
, sys.py
, json.py
. - Проверьте, какой именно модуль загружается:
import math
print(math.__file__) # Путь к загруженному модулю
Если у вас есть структура
/myproject
/utils
mymodule.py
Решение
Добавьте пустой
__init__.py
в utils/
: /myproject
/utils
__init__.py # Делаем utils пакетом
mymodule.py
Теперь импорт будет работать
from utils import mymodule
Иногда Python не находит модуль, если он находится вне стандартных путей. Решение
Добавьте путь вручную:
import sys
sys.path.append("/path/to/directory")
import mymodule # Теперь импорт будет работать
Абсолютный импорт (рекомендуется)
from myproject.utils.mymodule import my_function
Относительный импорт (используется внутри пакетов):
from .mymodule import my_function
Если импорт не работает, проверьте, какие модули загружены и где Python ищет файлы
import sys
print(sys.modules.keys()) # Список загруженных модулей
print(sys.path) # Пути, где Python ищет модули
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Python 3 не совместим с Python 2. Основные отличия: – другой синтаксис print,
– по-другому работают строки и деление,
– улучшенная поддержка Unicode,
– другие библиотеки и подходы к обработке данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍3💊2
Forwarded from easyoffer
Напоминаю, что в честь релиза запускаем акцию.
Первые 500 покупателей получат:
🚀 Скидку 50% на PRO тариф на 1 год
🎁 Подарок ценностью 5000₽ для тех, кто подписан на этот канал
🔔 Подпишитесь на этот канал: https://t.me/+b2fZN17A9OQ3ZmJi
В нем мы опубликуем сообщение о релизе в первую очередь
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
В Python все данные делятся на изменяемые (mutable) и неизменяемые (immutable)
После создания их нельзя изменить!
x = 10
print(id(x)) # 140735598722544 (адрес в памяти)
x = x + 5 # Создаётся новый объект!
print(id(x)) # 140735598722704 (новый адрес)
Пример:
str
неизменяемая s = "hello"
print(id(s)) # 140735598723664
s = s + " world" # Создаётся новая строка!
print(id(s)) # 140735598724240 (новый адрес)
Можно менять их содержимое без создания нового объекта.
lst = [1, 2, 3]
print(id(lst)) # 140735598722544
lst.append(4) # Изменяем список
print(id(lst)) # 140735598722544 (адрес остался тот же!)
Пример:
dict
изменяемый d = {"name": "Alice"}
print(id(d)) # 140735598723664
d["age"] = 25 # Добавляем ключ
print(id(d)) # 140735598723664 (адрес не изменился!)
Неизменяемые объекты безопаснее для ключей
dict
и set
d = {}
d[[1, 2, 3]] = "Ошибка!" # ❌ TypeError: unhashable type: 'list'
Используем
tuple
вместо list
(он неизменяемый) d[(1, 2, 3)] = "OK"
Ошибки с изменяемыми значениями по умолчанию
def add_item(lst=[]): # ❌ Опасный код!
lst.append(1)
return lst
print(add_item()) # [1]
print(add_item()) # [1, 1] ❌ Список не создаётся заново!
Используем
None
вместо списка def add_item(lst=None):
if lst is None:
lst = []
lst.append(1)
return lst
copy()
делает поверхностную копию (новый объект, но старые вложенные элементы). deepcopy()
делает глубокую копию (всё новое). import copy
lst1 = [[1, 2, 3], [4, 5, 6]]
lst2 = copy.copy(lst1) # Поверхностная копия
lst2[0][0] = 99
print(lst1) # [[99, 2, 3], [4, 5, 6]] ❌ Исходный список изменился!
Используем
deepcopy()
для полной независимой копии lst3 = copy.deepcopy(lst1)
lst3[0][0] = 100
print(lst1) # [[99, 2, 3], [4, 5, 6]] ✅ Не изменился!
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9