如何设置Django URL别名?及DRF视图集过滤器技术问题咨询
嘿,我来帮你搞定这两个问题!先从Django的URL别名设置说起,再聊聊怎么优化DRF过滤器的URL参数(同时保留你想用的DjangoFilterBackend)。
URL别名(通过name参数)是Django里避免硬编码URL的好办法,不管是在视图还是模板里,都能通过别名反向生成路径,维护起来超方便。具体操作分两步:
在URL配置里定义别名
不管是项目根urls.py还是应用的urls.py,配置路由时加上name参数就行。如果是用DRF的视图集,还可以通过basename来生成默认的别名前缀:# 项目根urls.py from django.urls import path, include urlpatterns = [ # 可选:加命名空间(namespace),避免不同应用的别名冲突 path('product/', include('products.urls', namespace='products')), ] # 应用的products/urls.py from django.urls import path from .views import ProductViewSet from rest_framework.routers import DefaultRouter router = DefaultRouter() # basename会生成类似product-list、product-detail的别名(对应ModelViewSet的不同动作) router.register(r'', ProductViewSet, basename='product') urlpatterns = router.urls如果是普通的类视图或函数视图,直接在
path里加name:path('product/<slug:slug>/', views.ProductDetailView.as_view(), name='product-detail')通过别名反向生成URL
- 在视图里用
reverse函数:from django.urls import reverse def some_view(request): # 带命名空间的写法 product_list_url = reverse('products:product-list') # 带参数的详情页URL product_detail_url = reverse('products:product-detail', kwargs={'slug': 'smart-phone'}) # 后续逻辑... - 在模板里用
{% url %}标签:<a href="{% url 'products:product-list' %}">产品列表</a> <a href="{% url 'products:product-detail' slug='smart-phone' %}">智能手机详情</a>
- 在视图里用
你现在的URL参数是category__slug和brand__slug,看起来有点冗长。如果想让参数更简洁(比如改成category和brand),完全不用换DjangoFilterBackend,自定义一个FilterSet就能搞定:
创建自定义FilterSet
在应用里新建一个filters.py文件,写自定义的过滤规则:import django_filters from .models import Product class ProductFilter(django_filters.FilterSet): # 用简洁的参数名,映射到模型的category__slug字段 category = django_filters.CharFilter(field_name='category__slug', lookup_expr='exact') # 同理处理brand参数 brand = django_filters.CharFilter(field_name='brand__slug', lookup_expr='exact') class Meta: model = Product fields = ['category', 'brand'] # 这里用自定义的参数名在视图集里替换filter_fields为filter_class
修改你的ProductViewSet,把原来的filter_fields换成自定义的filter_class:class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer lookup_field = 'slug' filter_backends = (SearchFilter, DjangoFilterBackend,) filter_class = ProductFilter # 替换成自定义的FilterSet这样生成的URL就会变成
http://*.compute.amazonaws.com:8000/product/?category=smart-phone&brand=asus,参数更友好,同时你依然在使用熟悉的DjangoFilterBackend。
内容的提问来源于stack exchange,提问作者sadaf2605

