Skip to content

Instantly share code, notes, and snippets.

@Miron-Anosov
Created January 28, 2025 14:16
Show Gist options
  • Save Miron-Anosov/6731b55877678d1f7a1635802091543f to your computer and use it in GitHub Desktop.
Save Miron-Anosov/6731b55877678d1f7a1635802091543f to your computer and use it in GitHub Desktop.

Django Views Documentation

Содержание

  1. Введение
  2. Базовое использование
  3. Продвинутые запросы
  4. Работа с файлами
  5. Массовые операции
  6. Лучшие практики
  7. Продвинутые техники

Введение

Данная документация описывает работу с Django views, включая классы-представления (Class-Based Views) и функции-представления (Function-Based Views). В документации представлены примеры базового и продвинутого использования, работа с файлами и рекомендуемые практики.

Базовое использование

Function-Based Views (FBV)

from django.shortcuts import render
from django.http import HttpRequest

def products_list(request: HttpRequest):
    context = {
        "products": Product.objects.all(),
    }
    return render(request, 'products-list.html', context=context)

Class-Based Views (CBV)

from django.views.generic import ListView

class ProductListView(ListView):
    template_name = 'products-list.html'
    context_object_name = 'products'
    queryset = Product.objects.filter(archived=False)

Продвинутые запросы

Оптимизация запросов

# Использование select_related для связей ForeignKey
class OrderListView(ListView):
    queryset = (
        Order.objects
        .select_related('user')  # для ForeignKey
        .prefetch_related("products")  # для ManyToMany
        .filter(status='active')
    )

# Сложные фильтры
class AdvancedProductListView(ListView):
    def get_queryset(self):
        return (
            Product.objects
            .filter(archived=False)
            .exclude(price__lt=100)
            .annotate(
                total_orders=Count('order'),
                revenue=Sum(F('price') * F('order__quantity'))
            )
            .order_by('-revenue')
        )

Кастомные менеджеры

class ProductManager(models.Manager):
    def active(self):
        return self.filter(archived=False)

    def with_sales_stats(self):
        return self.annotate(
            total_sales=Count('order'),
            revenue=Sum(F('price') * F('order__quantity'))
        )

class Product(models.Model):
    objects = ProductManager()

Работа с файлами

Загрузка файлов

from django.core.files.storage import default_storage

class ProductImageUploadView(UpdateView):
    model = Product
    fields = ['name', 'image']

    def form_valid(self, form):
        if 'image' in self.request.FILES:
            file = self.request.FILES['image']
            path = default_storage.save(
                f'products/{file.name}',
                file
            )
            self.object.image_path = path
        return super().form_valid(form)

Обработка больших файлов

from django.core.files.uploadhandler import TemporaryFileUploadHandler

class LargeFileUploadView(View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.upload_handlers = [TemporaryFileUploadHandler()]

    def post(self, request):
        chunk_size = 2500
        for chunk in request.FILES['file'].chunks(chunk_size):
            # Обработка чанка
            process_chunk(chunk)

Массовые операции

Bulk Create

def bulk_create_products(products_data):
    products = [
        Product(
            name=data['name'],
            price=data['price'],
            description=data['description']
        )
        for data in products_data
    ]
    return Product.objects.bulk_create(
        products,
        batch_size=100,
        ignore_conflicts=True
    )

Bulk Update

def bulk_update_prices(products, price_increase):
    for product in products:
        product.price += price_increase
    
    Product.objects.bulk_update(
        products,
        ['price'],
        batch_size=100
    )

Лучшие практики

1. Использование типизации

from typing import List, Optional
from django.db.models import QuerySet

class ProductService:
    def get_active_products(self) -> QuerySet[Product]:
        return Product.objects.filter(archived=False)

    def create_product(self, data: dict) -> Product:
        return Product.objects.create(**data)

2. Оптимизация производительности

class OptimizedListView(ListView):
    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.only('name', 'price')  # Выбираем только нужные поля

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['cached_categories'] = cache.get_or_set(
            'categories',
            lambda: list(Category.objects.all()),
            timeout=3600
        )
        return context

Продвинутые техники

1. Middleware для мониторинга

import time
from django.db import connection

class QueryCountMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        start_time = time.time()
        initial_queries = len(connection.queries)

        response = self.get_response(request)

        total_time = time.time() - start_time
        total_queries = len(connection.queries) - initial_queries

        print(f'Queries: {total_queries}, Time: {total_time:.2f}s')
        return response

2. Кастомные миксины

class SerializerMixin:
    serializer_class = None

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)

    def get_serialized_data(self):
        return self.get_serializer(self.get_queryset(), many=True).data

class ProductAPIView(SerializerMixin, ListView):
    serializer_class = ProductSerializer
    queryset = Product.objects.all()

    def get(self, request, *args, **kwargs):
        data = self.get_serialized_data()
        return JsonResponse(data, safe=False)

3. Динамическая фильтрация

class DynamicFilterMixin:
    def get_queryset(self):
        queryset = super().get_queryset()
        filter_params = {
            key: value
            for key, value in self.request.GET.items()
            if key in self.filterable_fields
        }
        return queryset.filter(**filter_params)

class ProductListView(DynamicFilterMixin, ListView):
    model = Product
    filterable_fields = ['category', 'price', 'archived']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment