← Назад к вопросам

Что такое re_path в Django?

2.0 Middle🔥 131 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

re_path в Django

re_path — это функция в Django для определения URL-маршрутов с использованием регулярных выражений (regex). Она позволяет создавать гибкие и сложные URL-паттерны, которые невозможно выразить стандартной функцией path().

История и различие от path()

Django предоставляет два основных способа определения URL-маршрутов:

# path() — простой синтаксис, без регулярных выражений
from django.urls import path

path('articles/<int:year>/', views.year_archive)

# re_path() — использует регулярные выражения для большей гибкости
from django.urls import re_path

re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive)

Основной синтаксис

from django.urls import re_path
from . import views

urlpatterns = [
    # Простой URL без параметров
    re_path(r'^$', views.index, name='index'),
    
    # URL с параметром года
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    
    # URL с несколькими параметрами
    re_path(
        r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',
        views.month_archive
    ),
    
    # URL с опциональным параметром
    re_path(r'^blog/(?P<slug>[-\w]+)/?$', views.blog_detail),
]

Компоненты регулярного выражения

# r'' — сырая строка (raw string), избегает экранирования
# ^ — начало строки
# $ — конец строки
# [0-9] — любая цифра (можно использовать \d)
# {4} — ровно 4 символа
# (?P<name>...) — именованная группа захвата
# [...] — класс символов
# + — один или более
# * — ноль или более
# ? — ноль или один
# | — или
# \w — буква, цифра, подчёркивание
# \d — цифра
# \s — пробел

Практические примеры

from django.urls import re_path
from . import views

urlpatterns = [
    # Пример 1: ID как положительное число
    re_path(r'^user/(?P<user_id>\d+)/$', views.user_detail),
    
    # Пример 2: Slug (буквы, цифры, дефисы, подчёркивания)
    re_path(r'^posts/(?P<slug>[-\w]+)/$', views.post_detail),
    
    # Пример 3: UUID
    re_path(
        r'^documents/(?P<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/$',
        views.document_detail
    ),
    
    # Пример 4: Email
    re_path(
        r'^contact/(?P<email>[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/$',
        views.contact_form
    ),
    
    # Пример 5: Вложенные ресурсы
    re_path(
        r'^users/(?P<user_id>\d+)/posts/(?P<post_id>\d+)/$',
        views.user_post_detail
    ),
    
    # Пример 6: Опциональная часть URL
    re_path(r'^products/(?P<category>[\w-]+)?/?$', views.products),
    
    # Пример 7: API версионирование
    re_path(r'^api/v(?P<version>\d+)/users/$', views.user_list),
]

Использование в view функциях

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Article, User

# Функция получает параметры из re_path()
def year_archive(request, year):
    articles = Article.objects.filter(pub_date__year=year)
    return render(request, 'articles/year_archive.html', {
        'year': year,
        'articles': articles
    })

def user_detail(request, user_id):
    user = get_object_or_404(User, id=int(user_id))
    return render(request, 'user_detail.html', {'user': user})

def nested_resource(request, user_id, post_id):
    # Оба параметра доступны
    user = get_object_or_404(User, id=int(user_id))
    post = get_object_or_404(Post, id=int(post_id), author=user)
    return render(request, 'post.html', {
        'user': user,
        'post': post
    })

Использование в class-based views

from django.views import View
from django.views.generic import DetailView
from .models import Article, Comment

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'article_detail.html'
    context_object_name = 'article'
    
    def get_object(self, queryset=None):
        article_id = self.kwargs.get('article_id')
        return get_object_or_404(Article, id=article_id)

urlpatterns = [
    re_path(
        r'^articles/(?P<article_id>\d+)/$',
        ArticleDetailView.as_view(),
        name='article-detail'
    ),
]

Конвертеры параметров

Так как re_path использует строки, нужно вручную преобразовывать типы:

def user_detail(request, user_id):
    # user_id — строка из URL, нужно преобразовать в int
    user = get_object_or_404(User, id=int(user_id))
    return render(request, 'user_detail.html', {'user': user})

# Или использовать декоратор
from django.views.decorators.http import require_http_methods

@require_http_methods(["GET"])
def year_archive(request, year):
    year = int(year)
    articles = Article.objects.filter(pub_date__year=year)
    return render(request, 'year_archive.html', {'articles': articles})

Сравнение path() и re_path()

from django.urls import path, re_path

# path() — более простой и читаемый
path('articles/<int:year>/', views.year_archive)

# re_path() — более гибкий, но многословный
re_path(r'^articles/(?P<year>[0-9]+)/$', views.year_archive)

# Сложный случай, где re_path() удобнее
re_path(
    r'^blog/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})-(?P<slug>[-\w]+)/$',
    views.blog_post_detail
)

# Эквивалент через path() был бы невозможен

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

# ❌ Плохо: сложное регулярное выражение
re_path(r'^(?P<code>[A-Z]{2}[0-9]{4}-?[A-Z0-9]{3,})/$', views.process_code)

# ✅ Хорошо: используйте path() где возможно
path('code/<str:code>/', views.process_code)

# ✅ Хорошо: используйте re_path() для сложных паттернов
re_path(r'^files/(?P<filepath>.+\.pdf)/$', views.serve_pdf)

# ✅ Хорошо: используйте именованные группы
re_path(
    r'^blog/(?P<year>\d{4})/(?P<month>\d{2})/$',
    views.monthly_archive,
    name='blog-monthly-archive'
)

# ✅ Хорошо: добавляйте комментарии к сложным паттернам
re_path(
    # URL формата: /api/v2/users/123/posts/456/
    r'^api/v(?P<version>\d+)/users/(?P<user_id>\d+)/posts/(?P<post_id>\d+)/$',
    views.user_post_detail
)

Вложенные URL-ы (include)

# urls.py (главный)
from django.urls import path, re_path, include

urlpatterns = [
    re_path(r'^api/', include('myapp.api.urls')),
    re_path(r'^blog/', include('blog.urls')),
]

# myapp/api/urls.py
from django.urls import re_path
from . import views

urlpatterns = [
    re_path(r'^v(?P<version>\d+)/users/$', views.user_list),
    re_path(r'^v(?P<version>\d+)/users/(?P<user_id>\d+)/$', views.user_detail),
]

# Результирующие URL:
# /api/v1/users/
# /api/v1/users/123/

Когда использовать re_path

  1. Сложные паттерны — когда path() недостаточно гибкий
  2. Легирующиеся URL — для совместимости со старым форматом
  3. Спецификации — когда URL должен соответствовать точной спецификации
  4. Валидация — когда нужна дополнительная валидация в самом URL

В большинстве случаев лучше использовать path(), так как он проще, безопаснее и быстрее. re_path() — это инструмент для специальных случаев.

Что такое re_path в Django? | PrepBro