Django
Django⚑
Переваги та недоліки Django⚑
Переваги Django
- Велика кількість готових компонентів та пакетів, які дозволяють швидко створювати складні веб-додатки.
- Гарна документація і велика спільнота, яка підтримує і розвиває фреймворк.
- Широкі можливості для роботи з базами даних і управління моделями даних.
- Вбудована адміністративна панель, яка дозволяє керувати даними і користувачами.
- Можливість створення REST API за допомогою Django REST framework.
Недоліки Django
- Проблеми з асинхронністю.
- Обмеженість у виборі технологій та підходів до розробки.
- Вищий поріг входження для початківців.
- Деякі аспекти роботи з базами даних можуть бути не дуже ефективними.
- Деякі компоненти Django можуть бути занадто громіздкими для простих проєктів.
Основні компоненти в Django⚑
Основні компоненти стандартного проекту Django
- Моделі - описують структуру бази даних.
- Django ORM - інструмент для роботи з базою даних.
- Представлення - визначають, як дані будуть відображатися на сторінках.
- URL-адреси - визначають, які представлення будуть викликатися при обробці запитів.
- Шаблони - визначають, як дані будуть відображатися на сторінках.
- Адміністративна панель - дозволяє керувати даними і користувачами.
- Фреймворк форм - спрощує роботу з формами на сторінках.
- Механізм міграцій - дозволяє оновлювати структуру бази даних без втрати даних.
- Засоби тестування - дозволяють автоматизувати тестування додатку.
Django ORM⚑
Django ORM (Object-Relational Mapping) — це компонент Django, який дозволяє взаємодіяти з базою даних, використовуючи об'єктно-орієнтовані моделі, замість написання сирих SQL-запитів. Він автоматично перетворює Python-код у SQL-запити, роблячи роботу з базами даних зручнішою і більш безпечною.
Основні переваги Django ORM
- Автоматизація створення таблиць і запитів.
- Захист від SQL-ін'єкцій.
- Зручний синтаксис для роботи з базою даних.
- Можливість гнучкої побудови складних запитів.
- Підтримка різних типів баз даних: PostgreSQL, MySQL, SQLite, Oracle тощо.
Основні компоненти Django ORM
- Моделі (Models)
- Моделі є основою ORM і визначають структуру таблиць у базі даних.
- Кожна модель в Django — це Python-клас, який успадковує
models.Model
. - Поля класу відповідають стовпцям таблиці бази даних.
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
-
Поля (Fields)
- Кожне поле моделі (
CharField
,IntegerField
,DateTimeField
, тощо) визначає тип даних у відповідному стовпці бази даних. - Можна додавати валідатори, налаштовувати значення за замовчуванням, встановлювати унікальність та інші параметри.
- Кожне поле моделі (
-
Менеджер об’єктів (QuerySet API)
objects
— це менеджер, за допомогою якого виконується доступ до записів у таблиці.- За допомогою менеджера можна створювати, читати, оновлювати та видаляти дані.
Product.objects.create(name="Laptop", price=1200.00) # Create object
products = Product.objects.all() # Getting all records
laptops = Product.objects.filter(name__icontains="laptop") # Filtering
-
Фільтри (Filters)
- Django ORM надає різноманітні методи для створення запитів:
filter()
,exclude()
,get()
. - Використовуються спеціальні ключі (наприклад,
__icontains
,__gte
), які визначають умови.
- Django ORM надає різноманітні методи для створення запитів:
-
Відношення (Relationships)
- Django підтримує зв'язки між моделями:
ForeignKey
,OneToOneField
,ManyToManyField
. - Це дозволяє створювати зв’язки між таблицями в базі даних.
- Django підтримує зв'язки між моделями:
class Category(models.Model):
name = models.CharField(max_length=100)
class Product(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
- Міграції (Migrations)
- Міграції — це механізм, що дозволяє перетворювати зміни у моделях на SQL-команди для синхронізації структури бази даних.
- Генерація та застосування міграцій
- Сигнали (Signals)
- Django дозволяє виконувати дії перед або після певних подій у моделях (наприклад, збереження, видалення записів).
- Наприклад,
pre_save
абоpost_delete
.
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Product)
def notify_new_product(sender, instance, created, **kwargs):
if created:
print(f"New product added: {instance.name}")
- Транзакції (Transactions)
- Django ORM підтримує атомарні операції через
transaction.atomic()
, що дозволяє виконувати кілька операцій як одну.
- Django ORM підтримує атомарні операції через
from django.db import transaction
with transaction.atomic():
category = Category.objects.create(name="Electronics")
Product.objects.create(name="Smartphone", category=category)
- Raw SQL
- Якщо потрібно виконати нестандартний SQL-запит, ORM дозволяє це зробити через метод
raw()
.
- Якщо потрібно виконати нестандартний SQL-запит, ORM дозволяє це зробити через метод
Компоненти Django ORM для запитів до БД⚑
Django ORM має кілька ключових компонентів, які забезпечують зручну та ефективну роботу з запитами до бази даних.
- QuerySet - надає основні інструменти для побудови SQL-запитів до бази даних.
- ModelManager - є "входом" до QuerySet, який додає можливість викликати стандартні та кастомні методи на рівні моделі.
-
Q - використовується для побудови складних логічних умов у запитах, що дозволяє гнучко фільтрувати дані.
-
QuerySet - це набір об'єктів, отриманих з бази даних за допомогою запитів. Це основний інструмент для отримання даних з таблиці. Він є ітерованим і може виконувати різноманітні операції для отримання, фільтрації, сортування, агрегування даних. QuerySet дозволяє будувати SQL-запити через Python, не пишучи сирий SQL.
- QuerySet будує SQL-запит "ліниво". Це означає, що запит до бази даних відбувається лише тоді, коли результати необхідно отримати (наприклад, через ітерацію).
products = Product.objects.all() # Get all objects
laptops = Product.objects.filter(name__icontains="laptop") # Filter
sorted_products = Product.objects.order_by('-price') # Sort
top_five = Product.objects.all()[:5] # Limit
- ModelManager - це інтерфейс для взаємодії з QuerySet. Кожна модель у Django автоматично має менеджер об'єктів
objects
, який дозволяє виконувати операції для отримання даних. Менеджер відповідає за створення, фільтрацію, видалення об'єктів та їх отримання з бази даних. Менеджери можна кастомізувати, щоб додавати власну логіку.
class ProductManager(models.Manager):
def expensive_products(self):
return self.filter(price__gt=1000)
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
objects = ProductManager() # Connecting a custom manager
expensive = Product.objects.expensive_products() # Using a custom manager
- Q (об'єкт умов) - використовується для створення складних умов у запитах, які об'єднують кілька фільтрів через логічні оператори
AND
таOR
. Це дозволяє будувати гнучкі запити, які не можна створити через стандартні методиfilter()
абоexclude()
. Використання Q є особливо корисним, коли потрібно динамічно будувати запити на основі різних умов.
from django.db.models import Q
products = Product.objects.filter(
Q(price__gt=1000) | Q(name__icontains="Laptop") # Get products with price greater than 1000 or name "Laptop"
)
products = Product.objects.filter(
Q(price__lt=500) & ~Q(name__icontains="Phone") # Combine conditions with exclusion
)
Що таке міграції?⚑
Міграції — це механізм для управління змінами в структурі бази даних, змінювати схему таблиці. Вони використовуються для створення, зміни або видалення таблиць і полів у базі даних без необхідності вручну виконувати SQL-запити
Команда makemigrations
генерує файл міграції, що містить інформацію про зміни, які потрібно застосувати. Міграції створюються автоматично при зміні моделей у коді.
Команда migrate
використовується для застосування цих міграцій до бази даних, таким чином забезпечуючи синхронізацію структури бази з моделями в коді. Міграції дозволяють відслідковувати версії змін та полегшують роботу команди над однією базою даних, забезпечуючи узгодженість структури. Django зберігає інформацію про вже виконані міграції у спеціальній таблиці, що дозволяє відкотити зміни або переконатися, що всі міграції були успішно виконані.
Також в міграціях доступна команда RunPython
— це спеціальна операція в міграціях Django, яка дозволяє виконувати довільний Python-код під час міграції бази даних.
Види наслідування моделей⚑
Існують три основні стилі успадкування
- Абстрактні базові класи
- Multi-table inheritance
- Proxy models
Abstract Base Classes Абстрактні базові класи використовуються, коли треба визначити спільний набір полів чи методів, які будуть спільно використовуватися кількома моделями. Ці класи не матимуть власних таблиць у базі даних. Дочірні моделі включатимуть поля та методи, визначені в абстрактному базовому класі.
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Employee(CommonInfo):
position = models.CharField(max_length=50)
salary = models.DecimalField(max_digits=10, decimal_places=2)
У цьому прикладі CommonInfo
є абстрактним базовим класом зі спільними полями (name
, created_at
, updated_at
). Модель Employee
успадковує від CommonInfo
, отримуючи ці поля без необхідності повторного визначення їх.
Multi-Table Inheritance Multi-table inheritance - кожний підклас має свою власну таблицю баз даних. Успадкування вводить зв’язки між дочірньою моделлю та кожним з її батьків (за допомогою автоматично створеного OneToOneField
).
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Place.objects.filter(name="Bob's Cafe")
Restaurant.objects.filter(name="Bob's Cafe")
p = Place.objects.get(id=12)
p.restaurant # If p is a Restaurant object, this will give the child class: <Restaurant: ...>
Proxy Models Проксі-моделі використовуються, коли треба змінити поведінку моделі на рівні Python, не змінюючи її поля або створюючи нову таблицю бази даних. Проксі-моделі корисні для застосування власних методів, менеджерів або мета-опцій до існуючої моделі.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
class ArticleWithImages(Article):
class Meta:
proxy = True
def display_images(self):
return f"This article with title '{self.title}' has some images."
У цьому прикладі ArticleWithImages
є проксі-моделлю, яка успадковується від моделі Article
. Вона не вводить нових полів або не створює нової таблиці, але може містити додаткові методи або змінювати поведінку існуючої моделі.
Links
Які способи реалізації моделі User є в Django⚑
У Django є 3 основні способи реалізації моделі користувача (User
).
Готова модель користувача в django.contrib.auth.models
Django надає готову модель користувача під назвою User
. Ця модель включає стандартні поля, такі як ім'я користувача (username
), електронна пошта (email
), пароль (password
), інші поля для керування правами та аутентифікацією.
Абстрактний користувач (AbstractUser
) Наслідування від AbstractUser
- дозволяє додати додаткові поля та методи до стандартної моделі користувача.
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
birthday = models.DateField(null=True, blank=True) # additional custom fields
Абстрактний базовий користувач (AbstractBaseUser
) Наслідування від AbstractBaseUser
- дозволяє створити власну модель користувача, не обов'язково використовуючи стандартні поля. Потрібно визначити поля для ідентифікації користувача та визначити методи для роботи з аутентифікацією.
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomUserManager(BaseUserManager):
...
class CustomUser(AbstractBaseUser):
...
objects = CustomUserManager()
Як реалізується зв'язок багато-до-багатьох на рівні бази даних⚑
У Django зв'язок "багато-до-багатьох" (many-to-many) реалізується через використання поля ManyToManyField
. На рівні бази, якщо є моделі A і B зі зв'язком багато-до-багатьох, створюється проміжна таблиця з назвою a_to_b
, яка містить ключ до A, ключ до B та додаткову інформацію, наприклад, час створення зв'язку. Ця таблиця з'єднується з A і B за допомогою операції JOIN
.
Наприклад, є моделі Author
і Book
, і кожен автор може написати багато книг, а кожна книга може бути написана багатьма авторами:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
authors = models.ManyToManyField(Author)
def __str__(self):
return self.title
Використання зв'язку багато-до-багатьох
- Додавання авторів до книги:
author1 = Author.objects.create(name='Author One')
author2 = Author.objects.create(name='Author Two')
book = Book.objects.create(title='Sample Book')
book.authors.add(author1, author2)
- Отримання авторів книги:
book = Book.objects.get(id=1)
authors = book.authors.all()
for author in authors:
print(author.name)
- Отримання книг автора:
author = Author.objects.get(id=1)
books = author.book_set.all()
for book in books:
print(book.title)
Різниця між select_related
та prefetch_related
⚑
У Django, select_related
та prefetch_related
— це два методи, які використовуються для оптимізації запитів до бази даних з метою зменшення кількості виконаних запитів і підвищення ефективності доступу до пов'язаних об'єктів. Проте їхня робота відрізняється.
select_related
- повертає QuerySet, який автоматично включає у вибірку дані зв'язаних об'єктів при виконанні запиту. Працює з ForeignKey та OneToOneField. Створює запит, який об'єднує зв'язані таблиці і включає додаткові поля в SELECT
prefetch_related
- повертає QuerySet, який отримує за один прохід зв'язані об'єкти для кожного з вказаних параметрів пошуку. Вибирає дані для кожного зв'язку окремо, і виконує об'єднання на рівні Python.
select_related
- Тип зв'язку: Використовується для оптимізації доступу до пов'язаних об'єктів через зв'язки ForeignKey або OneToOneField.
- Механізм: Виконує SQL-запит за допомогою операції JOIN, об'єднуючи пов'язані таблиці та отримуючи всі дані в одному запиті.
prefetch_related
- Тип зв'язку: Використовується для оптимізації доступу до пов'язаних об'єктів через зв'язки ManyToManyField або ForeignKey з багатьма елементами.
- Механізм: Виконує окремі SQL-запити для головної та пов'язаної таблиць, а потім зберігає їх у пам'яті і здійснює об'єднання на стороні Python.
books = Book.objects.prefetch_related('authors').all()
for book in books:
for author in book.authors.all():
print(author.name)
Що робить select_for_update
⚑
select_for_update
є методом в Django ORM, який дозволяє заблокувати вибрані записи бази даних для заборони їхньої зміни іншими транзакціями до завершення поточної транзакції. Тобто блокує вибрані записи для оновлення. Блокування буде автоматично видалено при завершенні транзакції.
Під капотом він використовує оператор SELECT ... FOR UPDATE
. Цей оператор використовується для управління конкуренцією між транзакціями, щоб уникнути конфліктів та забезпечити консистентність даних.
with transaction.atomic():
queryset = MyModel.objects.select_for_update().filter(name='example')
instance = queryset.first()
instance.value = 42
instance.save()
Оптимізація запитів⚑
Для того, щоб зменшити час відповіді від серверу, і якщо проблема в базі даних, можна використати наступні поради
- визначити запити, які можуть спричиняти проблеми
- бібліотека django-debug-toolbar, django-silk
- правильне використання індексів, уникнення Sequential Scan. Якщо таблиця занадто велика - партиціювання та шардування.
- витягувати тільки ті дані які необхідні (використання
only
,defer
,values
,values_list
) - уникати зайвих JOIN та UNION
- використати EXPLAIN (ANALYZE, BUFFERS) для аналізу довгих запитів
- перевірити на проблему N+1 запитів - використовувати
select_related
таprefetch_related
у запитах. - можна подивитись в сторону денормалізації або створення окремої таблиці або view для звітів
- налаштувати логування в базі даних довгих запитів
- PostgreSQL: log_min_duration_statement
- PostgreSQL: pg_stat_statements
- використовувати репліку для читання
- якщо завдання дозволяє, не обробляти в view, а перевести генерацію відповіді в асинхронну таску
- використовувати віконні функції,
LATERAL JOIN
- уникати
order_by("?")
Якщо дані не часто міняються, або є великі запити які довго обробляють дані, можна додати кешування.
Що таке сигнали? Навіщо вони потрібні? Назвіть основні.⚑
Сигнали - це події в екосистемі Django. За допомогою сигналів підсистеми сповіщають додаток про те, що сталося. Для читання сигналів програміст реєструє обробники сигналів.
Сигнали поширюються синхронно. Це означає, що якщо ми підписуємо сто обробників на один сигнал, то час, необхідний для повернення відповіді, збільшиться.
Основні сигнали - це початок запиту і його завершення, перед збереженням моделі і після нього, звернення до бази даних.
Важливо: сигнали моделей працюють індивідуально, тобто для однієї моделі. При пакетній обробці, наприклад, queryset.all().delete()
або queryset.all().update({'foo'=42})
, події про видалення або зміну не будуть викликані.
Request - Response lifecycle⚑
У Django запит представлено як екземпляр класу HttpRequest
. Об'єкт HttpRequest
містить інформацію про запит користувача - метод HTTP (наприклад, GET, POST), URL-адресу, Headers та будь-які надіслані дані (JSON, файл, дані форми)
- Перехоплення запиту
- сервер отримує запит і передає його до першого Middleware у ланцюжку. Middleware може здійснювати певні перевірки, наприклад, перевірку авторизації користувача або перевірку дійсності запиту. Якщо запит не відповідає критеріям Middleware, він може повернути помилку або передати запит до наступного Middleware.
- Маршрутизація запиту
- коли запит проходить крізь всі Middleware, сервер перевіряє, до якої в'юхи програми потрібно направити запит. Це зазвичай визначається за допомогою URL-адреси, яку ви вказали. У файлі
urls.py
ми пробуємо знайти відповідний паттерн у спискуurlpatterns
для адреси з запиту.
- коли запит проходить крізь всі Middleware, сервер перевіряє, до якої в'юхи програми потрібно направити запит. Це зазвичай визначається за допомогою URL-адреси, яку ви вказали. У файлі
- Обробка запиту в'юхою
- коли сервер визначив, яка в'юха повинна обробити запит, вона виконується. В'юха отримує запит та допоміжні дані, які необхідні для виконання дії, наприклад, дані з форми, які ви ввели. Під час виконання в'юха може викликати додаткові Middleware, які допоможуть виконати завдання.
- Генерація відповіді
- коли в'юха завершила виконання, сервер отримує відповідь. Це може бути HTML-сторінка, JSON-відповідь або будь-який інший тип відповіді, який сервер підтримує. Сервер відправляє цю відповідь назад до клієнта, який ініціював запит.
╔══════════════════╗ ╔══════════════════╗ ╔══════════════════╗ ╔══════════════════╗
║ CLIENT ║ ▶ ║ WEB SERVER ║ ▶ ║ WSGI ║ ▶ ║ Application ║
║ Browser ║ ◀ ║ Nginx ║ ◀ ║ Gunicorn ║ ◀ ║ Django ║
╚══════════════════╝ ╚══════════════════╝ ╚══════════════════╝ ╚══════════════════╝
Django Part
╔══════════════════╗ ╔══════════════════╗
║ REQUEST ║ ║ RESPONSE ║
╚══════════════════╝ ╚══════════════════╝
⬇ ⬆
╔═══════════════════════════════════════════╗
║ Middleware ║
╚═══════════════════════════════════════════╝
⬇ ⬆
╔══════════════════╗ ╔══════════════════╗
║ URL router ║ ▶ ║ View ║
╚══════════════════╝ ╚══════════════════╝
⬇ ⬆
╔══════════════════╗
║ ORM ║
╚══════════════════╝
⬇ ⬆
╔══════════════════╗
║ Database ║
╚══════════════════╝
Що таке Middleware, для чого, як реалізується⚑
Middleware - це проміжний шар, який реалізований як об'єкт, який обробляє вхідний запит або вихідну відповідь (як і view). Наприклад, він може додавати заголовки, робити попередні перевірки. Middleware використовується, коли потрібно обробити всі запити до додатка.
Під час обробки запиту на Django сервері, викликається ряд Middleware, які можуть змінювати поведінку сервера та додавати додаткову функціональність.
У Django, Middleware реалізується як клас з одним або кількома методами, такими як __init__
, __call__
. Middleware повинен повертати оброблений об'єкт (запит або відповідь) для подальшої обробки або викидати виняток, якщо щось не в порядку. У цьому випадку подальша обробка припиняється.
Для включення Middleware достатньо додати його шлях до списку MIDDLEWARE
.
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response # One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
Основні Middleware⚑
AuthenticationMiddleware
- перевіряє, чи авторизований користувач, авторизує користувача. Додає до запиту полеuser
.SessionMiddleware
- дозволяє використовувати сесії, щоб зберігати інформацію між запитами. Він створює та зберігає сесійні файли та додає інформацію про сесію - додає до запиту об'єктsession
.CsrfViewMiddleware
- перевіряє, що POST-запити відправлені з поточного домену. Додає CSRF-токени до форм та інших запитів POST, щоб запобігти атакам типу Cross-Site Request Forgery.MessageMiddleware
- дозволяє відображати повідомлення користувачам, наприклад, після успішного входу до системи. Передає користувачеві короткі повідомлення.GZipMiddleware
- стискає відповідь, щоб зменшити розмір відправленої даних та покращити швидкість відповіді.
Алгоритм роботи CSRF middleware⚑
При кожному запиті система генерує унікальний токен і встановлює його в куках. В кожній формі розміщується приховане поле csrf-token
з тим самим токеном. При відправці форми методом POST
Django перевіряє, чи співпадають поле форми і значення в куках. Якщо ні, це означає, що запит підроблений або відправлений з іншого домену.
Щоб звільнити якусь view від перевірки (наприклад, для API), достатньо обгорнути її декоратором csrf_except
.
Проміжний шар CSRF та шаблонний тег забезпечують легке використання захисту від атаки міжсайтового підроблення запиту. Цей тип атаки відбувається, коли зловмисний веб-сайт містить посилання, кнопку форми або деякий JavaScript, який призначений для виконання дій на вашому веб-сайті з використанням облікових даних авторизованого користувача, який відвідував зловмисний сайт у своєму браузері. Сюди також входить пов'язаний тип атаки "логін CSRF", коли атакований сайт вводить в оману браузер користувача, авторизовуючись на сайті з чужими обліковими даними.
Перший захист від атаки CSRF - це гарантія того, що GET-запити (і інші "безпечні" методи, визначені в 9.1.1 Safe Methods, HTTP 1.1) не мають побічних ефектів. Запити через "небезпечні" методи, такі як POST, PUT і DELETE, можуть бути захищені за допомогою описаних нижче кроків.
CSRF базується на наступних компонентах
- CSRF кука, яка встановлюється як випадкове число (сеанс незалежного випадкового слова, як це іноді називають), до якої інші сайти не матимуть доступу. Ця кука встановлюється за допомогою CsrfViewMiddleware. Вона повинна бути постійною, але, оскільки немає способу встановити куки, які ніколи не закінчуються, вона відправляється з кожною відповіддю, яка викликала django.middleware.csrf.get_token() (функція, яка використовувалась всередині для отримання CSRF токена).
- У всіх POST-формах додається приховане поле 'csrfmiddlewaretoken'. Значення поля дорівнює CSRF куці. Цю частину виконує шаблонний тег.
- Усі HTTP-запити, які не є GET, HEAD, OPTIONS або TRACE, повинні містити CSRF куку та поле 'csrfmiddlewaretoken' з правильним значенням. В іншому випадку користувач отримає помилку 403. Ця перевірка виконується в CsrfViewMiddleware.
- Крім того, для HTTPS-запитів в CsrfViewMiddleware перевіряється "referer" (вихідний запит). Це необхідно для запобігання атаки MITM (Man-In-The-Middle), яка можлива при використанні HTTPS і токена, який не прив'язаний до сеансу, оскільки клієнти приймають (на жаль) HTTP-заголовок 'Set-Cookie', незважаючи на те, що спілкування з сервером відбувається через HTTPS. (Ця перевірка не виконується для HTTP-запитів, оскільки заголовок "referer" легко підробити при використанні HTTP.) Якщо задано параметр CSRF_COOKIE_DOMAIN, значення "referer" буде порівнюватися з цим значенням. Значення підтримує піддомени. Наприклад, CSRF_COOKIE_DOMAIN = '.example.com' дозволяє відправляти POST-запити з
www.example.com
таapi.example.com
. Якщо параметр не вказано, "referer" повинен бути рівним HTTP-заголовку Host. Щоб розширити список доступних доменів, крім поточного хоста та домена кук, використовуйте CSRF_TRUSTED_ORIGINS.
Такий підхід гарантує, що лише форми, відправлені з довірених доменів, можуть передавати POST-дані.
GET-запити умисно ігноруються (а також всі інші запити, які вважаються "безпечними" згідно з RFC 2616). Ці запити ніколи не повинні виконувати будь-які потенційно небезпечні дії, і CSRF-атаки через GET-запит повинні бути безпечними. RFC 2616 визначає POST, PUT і DELETE як "небезпечні".
Що таке Meta в класах Django і для чого потрібен⚑
У Django, атрибут Meta
в класах використовується для визначення додаткової інформації (метадата) про клас моделі або серіалізатора.
Meta
дозволяє налаштовувати різні аспекти класу моделі або серіалізатора, такі як базова модель даних, ім'я таблиці бази даних, порядок сортування результатів запиту, валідацію даних та багато іншого.
Приклад Meta
для класу моделі в Django
class MyModel(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Meta:
ordering = ['name']
verbose_name_plural = 'My Models'
У цьому прикладі Meta
містить атрибути ordering
та verbose_name_plural
. ordering
вказує, що результати запиту до бази даних будуть сортовані за полем name
. verbose_name_plural
встановлює людський читабельний варіант назви для таблиці моделі в множинному числі.
Аналогічно, для класу серіалізатора в Django, Meta
може використовуватись для задання моделі, над якою буде працювати серіалізатор, та визначення списку полів, які повинні бути включені до серіалізації:
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['name', 'age']
Яка різниця між Django та Flask⚑
Django і Flask - це два популярні фреймворки для розробки веб-додатків на мові програмування Python. Основна різниця між Django і Flask полягає в підході до розробки і функціональних можливостях.
Ключові відмінності
- Комплексність та структура
- Django: Це комплексний фреймворк, який містить вбудовані інструменти і бібліотеки для багатьох аспектів веб-розробки, таких як аутентифікація, адміністративний інтерфейс, ORM (Object-Relational Mapping), тестування і т. д. Django визначає структуру проекту та накладає деякі обмеження на архітектуру.
- Flask: Це мінімалістичний фреймворк, який забезпечує базові інструменти для веб-розробки, залишаючи велику свободу вибору для програміста. Flask не нав'язує жодної певної структури або архітектури, що дозволяє розробникам використовувати тільки ті інструменти, які їм потрібні.
- Розмір проекту
- Django: Рекомендується для середніх і великих проектів, де важливо мати вбудовану підтримку для багатьох функцій і високорівневих компонентів.
- Flask: Підходить для невеликих і середніх проектів або тих, де потрібно збільшити гнучкість і незалежність від фреймворку.
- Навчання та складність
- Django: Має більший поріг навчання через велику кількість інструментів та концепцій, які необхідно зрозуміти.
- Flask: Є простим для навчання і зрозуміння, особливо для початківців, оскільки має менше обмежень і дозволяє швидко почати розробку.
- Інтеграція з іншими компонентами
- Django: Має вбудовані інструменти для багатьох аспектів, що дозволяє забезпечити швидку інтеграцію з різними функціями і бібліотеками.
- Flask: Вимагає більшої праці для налаштування та інтеграції з деякими функціями, оскільки зазвичай потрібно використовувати сторонні бібліотеки.
Вибір між Django і Flask залежить від потреб проекту та ваших власних уподобань. Якщо потрібна готова структура і широкий набір інструментів, то Django може бути кращим варіантом. Якщо потрібна більша гнучкість і контроль над проектом, проект невеликого розміру, то Flask може бути більш підходящим варіантом.
Як працює система аутентифікації в Django⚑
Django постачається з системою аутентифікації користувачів. Вона забезпечує користувацькі облікові записи, групи, права та сесії на основі куки.
Система аутентифікації Django відповідає як за аутентифікацію, так і за авторизацію. Коротко кажучи, аутентифікація перевіряє користувача, а авторизація визначає, що аутентифікований користувач може робити.
Система аутентифікації складається з
- Користувачів
- Прав: Бінарні (так/ні) прапори, які визначають наявність у користувача права виконувати певні дії.
- Груп: Загальний спосіб призначення міток та прав на множину користувачів.
- Налаштованої системи хешування паролів
- Інструментів для форм і представлень для аутентифікації користувачів або для обмеження доступу до вмісту
- Системи плагінів
Система аутентифікації Django намагається бути дуже простою і не надає деяких функцій, поширених в інших системах веб-аутентифікації. Ці функції реалізовані в сторонніх пакетах
- Перевірка складності пароля
- Обмеження спроб входу
- Аутентифікація через сторонні служби (наприклад, OAuth)
Як Django обробляє кілька з'єднань одночасно?⚑
Django - це веб-фреймворк, побудований на основі Python, і він використовує стандартний підхід до обробки кількох з'єднань одночасно, використовуючи багатопотоковий підхід.
Коли запит надходить до додатку Django, веб-сервер (такий як Apache або Nginx) направляє запит до додатку Django. Додаток Django потім створює новий потік для обробки запиту. Цей потік буде обробляти запит незалежно від будь-яких інших запитів, які можуть надходити одночасно.
Django використовує пул з'єднань з базою даних для керування з'єднаннями з базою даних. Коли потік повинен взаємодіяти з базою даних, він отримує з'єднання з пула з'єднань. Якщо всі з'єднання в пулі використані, потік буде очікувати, поки не звільниться доступне з'єднання.
За конфігурацією за замовчуванням, Django використовує максимум 5 потоків на процес, але це може бути змінено в налаштуваннях додатку. Крім того, Django може працювати з веб-серверами WSGI, такими як Gunicorn або uWSGI, які можуть створювати кілька процесів для обробки запитів, кожен зі своїм набором потоків.
Що таке gunicorn?⚑
Gunicorn - це WSGI-сервер (Web Server Gateway Interface), який використовується для обслуговування веб-додатків на Python. Він є швидким і надійним сервером, який може обробляти велику кількість запитів.
WSGI - це стандартний інтерфейс між веб-сервером і веб-додатком на Python. Він дозволяє розробникам використовувати будь-який веб-сервер і будь-який веб-додаток на Python, який підтримує інтерфейс WSGI.
Gunicorn підтримує кілька робочих процесів, що дозволяє обробляти велику кількість запитів. Крім того, він має багато налаштувань, які дозволяють налаштувати його для конкретних потреб проекту.
Gunicorn може використовуватися в процесі розробки ПО для обслуговування веб-додатків на Python. Він може бути інтегрований з іншими інструментами розробки, такими як Flask, Django і Pyramid, щоб обслуговувати веб-додатки на Python. Він також може використовуватися в якості проксі-сервера для балансування навантаження та кешування.