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

Как добавляешь URL в Django?

1.3 Junior🔥 291 комментариев
#Django

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

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

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

Как добавляешь URL в Django

Добавление URL в Django осуществляется через систему маршрутизации на основе файлов urls.py. Это мощный и гибкий механизм, который позволяет связать URL-пути с view функциями или классами.

Основные концепции

URL routing в Django работает через сопоставление URL-паттерна с view функцией или классом. Главный файл urls.py обычно находится в папке проекта (конфигурация Django), а отдельные приложения имеют свои файлы urls.py.

Структура проекта

project/
├── project/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py          ← Главный файл маршрутизации
│   └── wsgi.py
└── myapp/
    ├── migrations/
    ├── templates/
    ├── views.py
    ├── urls.py          ← URL для приложения
    └── models.py

1. Основной файл urls.py (проекта)

# project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('myapp.urls')),  # Подключаем URLs приложения
    path('blog/', include('blog.urls')),
]

# Для статических файлов в development
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

2. URL-ы приложения

# myapp/urls.py
from django.urls import path
from . import views

app_name = 'myapp'  # Namespace для URL names

urlpatterns = [
    # Простой путь
    path('', views.index, name='index'),
    
    # С параметром
    path('articles/<int:id>/', views.article_detail, name='article_detail'),
    path('articles/<str:slug>/', views.article_by_slug, name='article_by_slug'),
    
    # С несколькими параметрами
    path('users/<int:user_id>/posts/<int:post_id>/', views.user_post, name='user_post'),
]

3. FBV (Function-Based Views)

# myapp/views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Article

# Простой view
def index(request):
    return HttpResponse("Welcome to home page")

# View с параметром из URL
def article_detail(request, id):
    article = get_object_or_404(Article, id=id)
    return render(request, 'article_detail.html', {'article': article})

# View со строковым параметром
def article_by_slug(request, slug):
    article = get_object_or_404(Article, slug=slug)
    return render(request, 'article_detail.html', {'article': article})

# View с несколькими параметрами
def user_post(request, user_id, post_id):
    from django.contrib.auth.models import User
    from .models import Post
    
    user = get_object_or_404(User, id=user_id)
    post = get_object_or_404(Post, id=post_id, author=user)
    return render(request, 'post.html', {'post': post, 'user': user})

4. CBV (Class-Based Views)

# myapp/urls.py
from django.urls import path
from . import views

app_name = 'myapp'

urlpatterns = [
    path('articles/', views.ArticleListView.as_view(), name='article_list'),
    path('articles/<int:pk>/', views.ArticleDetailView.as_view(), name='article_detail'),
    path('articles/create/', views.ArticleCreateView.as_view(), name='article_create'),
    path('articles/<int:pk>/edit/', views.ArticleUpdateView.as_view(), name='article_edit'),
    path('articles/<int:pk>/delete/', views.ArticleDeleteView.as_view(), name='article_delete'),
]

# myapp/views.py
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Article
from .forms import ArticleForm

class ArticleListView(ListView):
    model = Article
    template_name = 'articles/list.html'
    context_object_name = 'articles'
    paginate_by = 10

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'articles/detail.html'
    context_object_name = 'article'

class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'articles/form.html'
    success_url = reverse_lazy('myapp:article_list')

class ArticleUpdateView(UpdateView):
    model = Article
    form_class = ArticleForm
    template_name = 'articles/form.html'
    success_url = reverse_lazy('myapp:article_list')

class ArticleDeleteView(DeleteView):
    model = Article
    template_name = 'articles/confirm_delete.html'
    success_url = reverse_lazy('myapp:article_list')

5. Типы параметров в URL

from django.urls import path, re_path
from . import views

urlpatterns = [
    # int — целое число
    path('posts/<int:id>/', views.post_detail, name='post_detail'),
    
    # str — строка (по умолчанию)
    path('articles/<str:slug>/', views.article_by_slug, name='article_by_slug'),
    
    # slug — строка с дефисами и подчёркиванием
    path('blogs/<slug:slug>/', views.blog_detail, name='blog_detail'),
    
    # uuid — UUID
    path('items/<uuid:uuid>/', views.item_detail, name='item_detail'),
    
    # path — строка с любыми символами (включая /)
    path('files/<path:filepath>/', views.serve_file, name='serve_file'),
    
    # Регулярные выражения (старый синтаксис, но ещё используется)
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.articles_by_year, name='articles_by_year'),
]

# View функции
def post_detail(request, id):
    pass

def article_by_slug(request, slug):
    pass

def blog_detail(request, slug):
    pass

def item_detail(request, uuid):
    pass

def serve_file(request, filepath):
    pass

def articles_by_year(request, year):
    pass

6. Использование include() для вложенных URLs

# project/urls.py
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/users/', include('users.urls')),
    path('api/v1/products/', include('products.urls')),
    path('blog/', include('blog.urls')),
]

# users/urls.py
from django.urls import path
from . import views

app_name = 'users'

urlpatterns = [
    path('', views.UserListView.as_view(), name='list'),
    path('<int:pk>/', views.UserDetailView.as_view(), name='detail'),
    path('<int:pk>/posts/', views.UserPostsView.as_view(), name='posts'),
]

# Итоговые пути:
# /api/v1/users/
# /api/v1/users/1/
# /api/v1/users/1/posts/

7. Динамическое создание URLs

# myapp/urls.py
from django.urls import path
from . import views

app_name = 'myapp'

# Динамическое создание URL patterns
resource_patterns = []
for resource in ['posts', 'comments', 'likes']:
    resource_patterns += [
        path(f'{resource}/', views.list_view, {'resource': resource}, name=f'{resource}_list'),
        path(f'{resource}/<int:id>/', views.detail_view, {'resource': resource}, name=f'{resource}_detail'),
    ]

urlpatterns = resource_patterns

8. Reverse URL (генерация URL в коде)

# В templates
<a href="{% url 'myapp:article_detail' id=article.id %}">{{ article.title }}</a>
<a href="{% url 'myapp:article_list' %}">Back to articles</a>

# В Python коде
from django.urls import reverse
from django.shortcuts import redirect

def create_article(request):
    if form.is_valid():
        article = form.save()
        # Динамическая генерация URL
        url = reverse('myapp:article_detail', kwargs={'pk': article.id})
        return redirect(url)

def get_absolute_url(self):
    """В модели"""
    return reverse('myapp:article_detail', kwargs={'pk': self.pk})

9. Query параметры

# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('search/', views.search, name='search'),
]

# myapp/views.py
def search(request):
    # Query параметры — это GET параметры
    query = request.GET.get('q', '')          # /search/?q=django
    category = request.GET.get('category')    # /search/?q=django&category=tutorial
    page = request.GET.get('page', 1)
    
    results = Article.objects.filter(
        title__icontains=query
    )
    
    if category:
        results = results.filter(category=category)
    
    paginator = Paginator(results, 10)
    page_obj = paginator.get_page(page)
    
    return render(request, 'search.html', {'page_obj': page_obj})

# В template
<a href="{% url 'search' %}?q=django&category=tutorial">Search</a>

10. Перенаправления и ошибки

# myapp/urls.py
from django.urls import path
from django.views.generic import RedirectView
from . import views

urlpatterns = [
    # Перенаправление на другой URL
    path('old-url/', RedirectView.as_view(url='new-url/')),
    
    # Перенаправление по имени URL
    path('old-posts/', RedirectView.as_view(pattern_name='myapp:article_list')),
    
    # Обработка 404
    path('', views.index),
]

# settings.py
HANDLER404 = 'myapp.views.custom_404'
HANDLER500 = 'myapp.views.custom_500'

# views.py
def custom_404(request, exception):
    return render(request, '404.html', status=404)

def custom_500(request):
    return render(request, '500.html', status=500)

Best Practices

# ✅ ПРАВИЛЬНО: используй app_name для namespace
app_name = 'myapp'

urlpatterns = [
    path('', views.index, name='index'),
]

# ✅ ПРАВИЛЬНО: БЕЗ trailing slash
path('articles/', views.list)  # /articles
# ❌ НЕПРАВИЛЬНО: с trailing slash
path('articles/', views.list)  # /articles/

# ✅ ПРАВИЛЬНО:描述性имена
path('posts/<int:post_id>/comments/', views.post_comments, name='post_comments')

# ✅ ПРАВИЛЬНО: используй reverse для генерации URL
url = reverse('myapp:article_detail', kwargs={'pk': 1})

# ❌НЕПРАВИЛЬНО: hardcode URLs
url = f'/articles/{article.id}/'  # Плохая практика

Распространённые проблемы

# ПРОБЛЕМА 1: порядок URL patterns важен
urlpatterns = [
    path('<str:slug>/', views.generic),  # Ловит ВСЕ пути
    path('special/', views.special),     # Никогда не будет вызван!
]

# РЕШЕНИЕ: более специфичные пути первыми
urlpatterns = [
    path('special/', views.special),     # Более специфичный
    path('<str:slug>/', views.generic),  # Более общий
]

# ПРОБЛЕМА 2: забыли app_name
# В template: {% url 'article_detail' %} — не работает
# РЕШЕНИЕ: добавить app_name и использовать namespace
app_name = 'myapp'
# В template: {% url 'myapp:article_detail' %}

Вывод

  1. Главный urls.py — подключает URL из приложений через include()
  2. urls.py приложения — определяет маршруты для конкретного функционала
  3. FBV vs CBV — используй CBV для CRUD, FBV для уникальной логики
  4. Параметры URL<int:id>, <str:slug>, <uuid:uuid>
  5. Reverse — генерируй URL в коде через reverse() вместо hardcode
  6. Namespace — используй app_name для организации URL names
  7. Порядок важен — более специфичные пути должны быть первыми
Как добавляешь URL в Django? | PrepBro