Наш проект использует Django, Django-Rest-Framework и drf_yasg для документирования нашего API с помощью swagger. Я создал сериализатор, и я использую его с моим методом POST. все работает хорошо, все поля присутствуют на моей странице чванства.
Я создал метод удаления, используя тот же сериализатор, и документация swagger показывает в качестве параметров API только первую группу полей.
Я пытался использовать
@swagger_auto_schema(
method='post',
operation_description="POST /Rules/list/",
responses={200: listResponseSerializer()},
)
@swagger_auto_schema(
@swagger_auto_schema(responses={200: listResponseSerializer()})
method='delete',
operation_description="DELETE /Rules/list/",
responses={200: listResponseSerializer()},
)
@action(detail=False, methods=['post', 'delete'])
и есть один метод. оба метода post и delete немедленно отсутствуют на странице документации.
и при использовании
@swagger_auto_schema(responses={200: listResponseSerializer()})
Метод Post работает, но не метод удаления.
этот снимок показывает хорошие результаты метода POST, где все поля представлены в документации API. фильтры, параметры и др.
С DELETE он показывает только фильтры и игнорирует все остальные поля, присутствующие в сериализаторе.
Надеюсь, кто-нибудь может мне помочь с этим. Я борюсь с этим уже пару дней. Я не понимаю, чего мне не хватает или какую часть интеграции между django и swagger я не понимаю, и мне нужна помощь.
views.py:
class ActionAPIView(generics.GenericAPIView):
"""
Base class for all Action views so the filtering is automatically inserted
"""
filter_class = RESTRuleFilter
def get_queryset(self):
return Rule.objects.allowed_to_user(self.request.user)
def filter_queryset(self, queryset):
serializer = self.get_serializer(data=self.request.data)
if serializer.is_valid():
if 'filter' in serializer.validated_data:
filter = RESTRuleFilter(serializer.validated_data['filter'], queryset=queryset)
return filter.qs
return queryset
def get_serializer(self, *args, **kwargs):
return listSerializer(*args, **kwargs)
class listItemsApi(ActionAPIView):
"""
post:
add one or more Items to selected Rule list
delete:
remove one or more Items to selected Rule list
"""
def get_queryset(self):
return Rule.objects.allowed_to_user(self.request.user)
def get_serializer(self, *args, **kwargs):
return listPostSerializer(*args, **kwargs)
def get_delete_serializer(self, *args, **kwargs):
return listSerializer(*args, **kwargs)
def get_channel(self, list_id):
bu_list = []
for i in list_id:
bu = Channel.objects.allowed_to_user(self.request.user).get(
pk=i
)
bu_list.append({"pk": bu.id, "name": bu.name})
return bu_list
@swagger_auto_schema(responses={200: listResponseSerializer()})
def post(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
selected_Rules = serializer.get_selected_Rules(queryset)
bu_ids, cluster_list, Rules_id = self.build_sets(selected_Rules)
bu = self.get_channel(bu_ids)
task_id, timestamp = "sample_task_001"
response = {
"channels": bu,
"task_id": task_id,
}
return Response(response, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
в serializer.py:
class listItemsSerializer(serializers.Serializer):
block_item = serializers.CharField(required=False, allow_blank=True)
never_log_item = serializers.BooleanField(required=False, default=False)
never_learn_item = serializers.BooleanField(required=False, default=False)
description = serializers.CharField(required=False, allow_blank=True)
class listFiltersSerializer(serializers.Serializer):
name = serializers.CharField(required=False, allow_blank=True)
cluster = serializers.CharField(required=False, allow_blank=True)
channel = serializers.CharField(required=False, allow_blank=True)
partition = serializers.CharField(required=False, allow_blank=True)
class listSerializer(serializers.Serializer):
filters = listFiltersSerializer(required=False, help_text="list of Rules filters")
items = serializers.ListField(child=serializers.CharField(), required=True)
selected = serializers.ListField(child=serializers.IntegerField(), required=False, write_only=True)
select_all = serializers.BooleanField(
default=False,
write_only=True,
help_text=("Set to True to select all objects"),
)
def validate(self, data):
"""
Check if either both selected_status and select_all are configured or
we have a list of selected entries in selected
"""
user = get_current_user()
if data["select_all"]:
return data
if data["select_all"] is False and (
"selected" not in data or not data["selected"]
):
raise serializers.ValidationError(
"You must specify either select_all or selected"
)
found_count = 0
if "selected" in data and data["selected"]:
for d in data["selected"]:
if Rule.objects.allowed_to_user(user).filter(pk=d).exists():
found_count += 1
if found_count != len(data["selected"]):
raise serializers.ValidationError(
"Some of the selected items are invalid"
)
return data
def get_selected_Rules(self, queryset=None):
if queryset is None:
queryset = Rule.objects.all()
if self.validated_data.get('select_all', False):
return queryset
else:
return queryset.filter(pk__in=self.validated_data['selected'])
class listPostSerializer(listSerializer):
params = listItemsSerializer(
required=True, help_text="list of Itemss and setting to apply on selected Rules"
)
filters.py:
class RESTRuleFilter(RESTFilterSet):
name = django_filters.CharFilter(
lookup_expr="icontains", help_text="Rule name containing"
)
cluster = django_filters.ModelMultipleChoiceFilter(
queryset=Cluster.objects.all()
)
channel = django_filters.ModelMultipleChoiceFilter(
queryset=Channel.objects.all(), method="subfilter"
)
partition = django_filters.CharFilter(
lookup_expr="icontains", help_text="Partition name containing"
)
enforcement_mode = django_filters.CharFilter(
lookup_expr="icontains",
label="Enforcement Mode",
help_text="Enforcement Mode containing",
)
signatureset_name = django_filters.CharFilter(
label="Rule containing a signature set matching this string",
field_name="signatureset",
method="subfilter",
)
class Meta:
model = Rule
fields = (
"name",
"cluster",
"channel",
"partition",
"xxxxxxx",
"yyyyyyy",
)
urls.py:
schema_view = get_schema_view(
openapi.Info(
title="WAF Management Portal API",
default_version="v1",
description="REST api for interaction between Frontend and Backend.",
contact=openapi.Contact(email="xxx@email.com"),
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [
path(
"",
schema_view.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
path(
"rule/", ruleListAPIView.as_view(), name="rule_list_view_api"
),
path(
"rules/list/", listItemsApi.as_view(), name="list_api"
),
]
models.py:
class Channel(models.Model):
name = models.CharField(max_length=1024, db_index=True, unique=True)
class Cluster(models.Model):
name = models.CharField(max_length=1024, db_index=True, unique=True)
channel = models.ForeignKey(
Channel, on_delete=models.SET_NULL, null=True
)
class rule(models.Model):
app_id = models.CharField(max_length=32, db_index=False)
cluster = models.ForeignKey(
Cluster, on_delete=models.CASCADE, related_name="rules", null=True
)
name = models.CharField(max_length=1024, db_index=True)
partition = models.CharField(max_length=128, db_index=True)
objects = ruleManager()
class Meta:
verbose_name_plural = "rules"
unique_together = ("app_id", "cluster")
indexes = [models.Index(fields=["app_id", "cluster"])]
def __str__(self):
return self.full_path