Комментарии (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' %}
Вывод
- Главный
urls.py— подключает URL из приложений черезinclude() urls.pyприложения — определяет маршруты для конкретного функционала- FBV vs CBV — используй CBV для CRUD, FBV для уникальной логики
- Параметры URL —
<int:id>,<str:slug>,<uuid:uuid> - Reverse — генерируй URL в коде через
reverse()вместо hardcode - Namespace — используй
app_nameдля организации URL names - Порядок важен — более специфичные пути должны быть первыми