Skills Plugins MCP Prompt Model 博客 我的中心

django-drf

Django REST Framework patterns. Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions, filtersets). For Prowler API specifics (RLS/RBAC/Providers), also use prowler-api.

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=prowler-cloud-prowler-skills-django-drf-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name django-drf description Django REST Framework patterns. Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions, filtersets). For Prowler API specifics (RLS/RBAC/Providers), also use prowler-api. license Apache-2.0 metadata {"author":"prowler-cloud","version":"1.2.0","scope":["root","api"],"auto_invoke":["Creating ViewSets, serializers, or filters in api/","Implementing JSON:API endpoints","Adding DRF pagination or permissions"]} allowed-tools Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task Critical Patterns ALWAYS separate serializers by operation: Read / Create / Update / Include ALWAYS use filterset_class for complex filtering (not filterset_fields ) ALWAYS validate unknown fields in write serializers (inherit BaseWriteSerializer ) ALWAYS use select_related / prefetch_related in get_queryset() to avoid N+1 ALWAYS handle swagger_fake_view in get_queryset() for schema generation ALWAYS use @extend_schema_field for OpenAPI docs on SerializerMethodField NEVER put business logic in serializers - use services/utils NEVER use auto-increment PKs - use UUIDv4 or UUIDv7 NEVER use trailing slashes in URLs ( trailing_slash=False ) Note: swagger_fake_view is specific to drf-spectacular for OpenAPI schema generation. Implementation Checklist When implementing a new endpoint, review these patterns in order: # Pattern Reference Key Points 1 Models api/models.py UUID PK, inserted_at / updated_at , JSONAPIMeta.resource_name 2 ViewSets api/base_views.py , api/v1/views.py Inherit BaseRLSViewSet , get_queryset() with N+1 prevention 3 Serializers api/v1/serializers.py Separate Read/Create/Update/Include, inherit BaseWriteSerializer 4 Filters api/filters.py Use filterset_class , inherit base filter classes 5 Permissions api/base_views.py required_permissions , set_required_permissions() 6 Pagination api/pagination.py Custom pagination class if needed 7 URL Routing api/v1/urls.py trailing_slash=False , kebab-case paths 8 OpenAPI Schema api/v1/views.py @extend_schema_view with drf-spectacular 9 Tests api/tests/test_views.py JSON:API content type, fixture patterns Full file paths : See references/file-locations.md Decision Trees Which Serializer? GET list/retrieve → <Model>Serializer POST create → <Model>CreateSerializer PATCH update → <Model>UpdateSerializer ?include=... → <Model>IncludeSerializer Which Base Serializer? Read-only serializer → BaseModelSerializerV1 Create with tenant_id → RLSSerializer + BaseWriteSerializer (auto-injects tenant_id on create) Update with validation → BaseWriteSerializer (tenant_id already exists on object) Non-model data → BaseSerializerV1 Which Filter Base? Direct FK to Provider → BaseProviderFilter FK via Scan → BaseScanProviderFilter No provider relation → FilterSet Which Base ViewSet? RLS-protected model → BaseRLSViewSet (most common) Tenant operations → BaseTenantViewset User operations → BaseUserViewset No RLS required → BaseViewSet (rare) Resource Name Format? Single word model → plural lowercase (Provider → providers) Multi-word model → plural lowercase kebab (ProviderGroup → provider-groups) Through/join model → parent-child pattern (UserRoleRelationship → user-roles) Aggregation/overview → descriptive kebab plural (ComplianceOverview → compliance-overviews) Serializer Patterns Base Class Hierarchy # Read serializer (most common) class ProviderSerializer ( RLSSerializer ): class Meta : model = Provider fields = [ "id" , "provider" , "uid" , "alias" , "connected" , "inserted_at" ] # Write serializer (validates unknown fields) class ProviderCreateSerializer (RLSSerializer, BaseWriteSerializer): class Meta : model = Provider fields = [ "provider" , "uid" , "alias" ] # Include serializer (sparse fields for ?include=) class ProviderIncludeSerializer ( RLSSerializer ): class Meta : model = Provider fields = [ "id" , "alias" ] # Minimal fields SerializerMethodField with OpenAPI from drf_spectacular.utils import extend_schema_field class ProviderSerializer ( RLSSerializer ): connection = serializers.SerializerMethodField(read_only= True ) @extend_schema_field( { "type" : "object" , "properties" : { "connected" : { "type" : "boolean" }, "last_checked_at" : { "type" : "string" , "format" : "date-time" }, }, } ) def get_connection ( self, obj ): return { "connected" : obj.connected, "last_checked_at" : obj.connection_last_checked_at, } Included Serializers (JSON:API) class ScanSerializer ( RLSSerializer ): included_serializers = { "provider" : "api.v1.serializers.ProviderIncludeSerializer" , } Sensitive Data Masking def to_representation ( self, instance ): data = super ().to_representation(instance) # Mask by default, expose only on explicit request fields_param = self .context.get( "request" ).query_params.get( "fields[my-model]" , "" ) if "api_key" in fields_param: data[ "api_key" ] = instance.api_key_decoded else : data[ "api_key" ] = "****" if instance.api_key else None return data ViewSet Patterns get_queryset() with N+1 Prevention Always combine swagger_fake_view check with select_related / prefetch_related : def get_queryset ( self ): # REQUIRED: Return empty queryset for OpenAPI schema generation if getattr ( self , "swagger_fake_view" , False ): return Provider.objects.none() # N+1 prevention: eager load relationships return Provider.objects.select_related( "tenant" , ).prefetch_related( "provider_groups" , Prefetch( "tags" , queryset=ProviderTag.objects. filter (tenant_id= self .request.tenant_id)), ) Why swagger_fake_view? drf-spectacular introspects ViewSets to generate OpenAPI schemas. Without this check, it executes real queries and can fail without request context. Action-Specific Serializers def get_serializer_class ( self ): if self .action == "create" : return ProviderCreateSerializer elif self .action == "partial_update" : return ProviderUpdateSerializer elif self .action in [ "connection" , "destroy" ]: return TaskSerializer return ProviderSerializer Dynamic Permissions per Action class ProviderViewSet ( BaseRLSViewSet ): required_permissions = [Permissions.MANAGE_PROVIDERS] def set_required_permissions ( self ): if self .action in [ "list" , "retrieve" ]: self .required_permissions = [] # Read-only = no permission else : self .required_permissions = [Permissions.MANAGE_PROVIDERS] Cache Decorator from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_control CACHE_DECORATOR = cache_control( max_age=django_settings.CACHE_MAX_AGE, stale_while_revalidate=django_settings.CACHE_STALE_WHILE_REVALIDATE, ) @method_decorator( CACHE_DECORATOR, name= "list" ) @method_decorator( CACHE_DECORATOR, name= "retrieve" ) class ProviderViewSet ( BaseRLSViewSet ): pass Custom Actions # Detail action (operates on single object) @action( detail= True , methods=[ "post" ], url_name= "connection" ) def connection ( self, request, pk= None ): instance = self .get_object() # Process instance... # List action (operates on collection) @action( detail= False , methods=[ "get" ], url_name= "metadata" ) def metadata ( self, request ): queryset = self .filter_queryset( self .get_queryset()) # Aggregate over queryset... Filter Patterns Base Filter Classes class BaseProviderFilter ( FilterSet ): """For models with direct FK to Provider""" provider_id = UUIDFilter(field_name= "provider__id" , lookup_expr= "exact" ) provider_id__in = UUIDInFilter(field_name= "provider__id" , lookup_expr= "in" ) provider_type = ChoiceFilter(field_name= "provider__provider" , choices=Provider.ProviderChoices.choices) class BaseScanProviderFilter ( FilterSet ): """For models with FK to Scan (Scan has FK to Provider)""" provider_id = UUIDFilter(field_name= "scan__provider__id" , lookup_expr= "exact" ) Custom Multi-Value Filters class UUIDInFilter (BaseInFilter, UUIDFilter): pass class CharInFilter (BaseInFilter, CharFilter): pass class ChoiceInFilter (BaseInFilter, ChoiceFilter): pass ArrayField Filtering # Single value contains region = CharFilter(method= "filter_region" ) def filter_region ( self, queryset, name, value ): return queryset. filter (resource_regions__contains=[value]) # Multi-value overlap region__in = CharInFilter(field_name= "resource_regions" , lookup_expr= "overlap" ) Date Range Validation def filter_queryset ( self, queryset ): # Require date filter for performance if not (date_filters_provided): raise ValidationError([{ "detail" : "At least one date filter is required" , "status" : 400 , "source" : { "pointer" : "/data/attributes/inserted_at" }, "code" : "required" , }]) # Validate max range if date_range > settings.FINDINGS_MAX_DAYS_IN_RANGE: raise ValidationError(...) return super ().filter_queryset(queryset) Dynamic FilterSet Selection def get_filterset_class ( self ): if self .action in [ "latest" , "metadata_latest" ]: return LatestFindingFilter return FindingFilter Enum Field Override class Meta : model = Finding filter_overrides = { FindingDeltaEnumField: { "filter_class" : CharFilter}, StatusEnumField: { "filter_class" : CharFilter}, SeverityEnumField: { "filter_class" : CharFilter}, } Performance Patterns PaginateByPkMixin For large querysets with expensive joins: class PaginateByPkMixin : def paginate_by_pk ( self, request, base_queryset, manager, select_related= None , prefetch_related= None ): # 1. Get PKs only (cheap) pk_list = base_queryset.values_list( "id" , flat= True ) page = self .paginate_queryset(pk_list) # 2. Fetch full objects for just the page queryset = manager. filter (id__in=page) if select_related: queryset = queryset.select_related(*select_related) if prefetch_related: queryset = queryset.prefetch_related(*prefetch_related) # 3. Re-sort to preserve DB ordering queryset = sorted (queryset, key= lambda obj: page.index(obj. id )) return self .get_paginated_response( self .get_serializer(queryset, many= True ).data) Prefetch in Serializers def get_tags ( self, obj ): # Use prefetched tags if available if hasattr (obj, "prefetched_tags" ): return {tag.key: tag.value for tag in obj.prefetched_tags} # Fallback (causes N+1 if not prefetched) return obj.get_tags( self .context.get( "tenant_id" )) Naming Conventions Entity Pattern Example Serializer (read) <Model>Serializer ProviderSerializer Serializer (create) <Model>CreateSerializer ProviderCreateSerializer Serializer (update) <Model>UpdateSerializer ProviderUpdateSerializer Serializer (include) <Model>IncludeSerializer ProviderIncludeSerializer Filter <Model>Filter ProviderFilter ViewSet <Model>ViewSet ProviderViewSet OpenAPI Documentation from drf_spectacular.utils import extend_schema, extend_schema_view @extend_schema_view(
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。