Skip to content

fix: swagger show more args#2438

Merged
liuruibin merged 1 commit intomainfrom
pr@main@fix_swagger
Feb 28, 2025
Merged

fix: swagger show more args#2438
liuruibin merged 1 commit intomainfrom
pr@main@fix_swagger

Conversation

@shaohuzhang1
Copy link
Copy Markdown
Contributor

fix: swagger show more args

@f2c-ci-robot
Copy link
Copy Markdown

f2c-ci-robot bot commented Feb 28, 2025

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@f2c-ci-robot
Copy link
Copy Markdown

f2c-ci-robot bot commented Feb 28, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

],
tags=[_("Application/Conversation Log")]
)
@has_permissions(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provided code has several optimizations and corrections suggested to enhance its structure, performance, and adherence to best practices:

Optimizations:

  1. Imports:

    • Removed duplicate from django.utils.translation import gettext_lazy as _.
    • Combined imports under each section where necessary.
  2. Method Separation:

    • Moved the UploadFile view outside of the main API class.
    • Added an explanation comment about separating views.
  3. Docstring Corrections:

    • Updated docstrings to match current conventions.
    • Corrected method names (e.g., class DeleteFilesView(ListAPIView) should be DeleteFilesView).
  4. Parameter Formatting:

    • Ensured consistent parameter formatting using OpenAPI parameters.
  5. Comments:

    • Added comments to explain code sections and logic.
  6. Code Readability:

    • Improved readability by breaking down complex operations into smaller methods.

Potential Issues Suggested for Improvement:

  1. Permissions Check:

    • Ensure that the @has_permissions decorator is correctly linked to the appropriate endpoint or if it's being used in the correct place.
  2. Error Handling:

    • Consider adding error handling within the upload method for missing or invalid data.
  3. Logging / Debugging:

    • Implement logging to track file uploads and errors for debugging purposes.
  4. Validation:

    • Add validation on uploaded files to ensure they meet certain criteria such as file size limits or types.

Revised Version with Suggestions Implemented:

# utils.py
from django.utils.translation import gettext_lazy as _

# serializers.py
from rest_framework import generics, status

# exceptions.py
class CustomException(Exception):
    pass

# permissions.py
def has_permissions(request):
    # TODO: Implement actual permission checking logic here
    return True

# api_views.py
class ChatRecordApi(generics.ListAPIView):
    authentication_classes = ['TokenAuth']

    @staticmethod
    def get_request_params_api():
        # Define request parameters for Swagger/OpenAPI documentation
        return [
            openapi.Parameter(name='application_id', in_=openapi.IN_PATH, type=openapi.TYPE_STRING, required=True),
            openapi.Parameter(name='chat_id', in_=openapi.IN_PATH, type=openapi.TYPE_STRING, required=True)
        ]

class ApplicationListView(generics.ListCreateAPIView):
    queryset = YourModel.objects.all()
    serializer_class = YourSerializer

    def create(self, request):
        try:
            instance = self.serializer.save(request.data)
            return Response(instance.id, status=status.HTTP_201_CREATED)
        except CustomException as e:
            return JsonResponse({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

class ConversationLog(APIView):
    def post(self, request: Request, application_id: str, chat_log_type: str) -> Response:
        # Logic for creating a new conversation log entry
        pass

class UploadFile(APIView):
    authentication_classes = [TokenAuth]
    parser_classes = [MultiPartParser]

    @swagger_auto_schema(operation_summary="Upload files",
                         operation_id="Upload files",
                         manual_parameters=[
                             openapi.Parameter(name='application_id',
                                             in_=openapi.IN_PATH,
                                                 type=openapi.TYPE_STRING,
                                                 required=True,
                                                 description=_('Application ID')),
                             openapi.Parameter(name='chat_id',
                                             in_=openapi.IN_PATH,
                                                 type=openapi.TYPE_STRING,
                                                 required=True,
                                                 description=_('Conversation ID')),
                             openapi.Parameter(name='file',
                                             in_=openapi.IN_FORM,
                                             type=openapi.TYPE_FILE,
                                             required=True,
                                             description=_('Upload file'))
                         ],
                         tags=["Application/Conversation Log"]
                        )
    def post(self, request: Request, application_id: str, chat_id: str) -> Response:
        if not has_permissions(request):
            return JsonResponse({"detail": "Unauthorized"}, status=HTTP_403_FORBIDDEN)
        
        try:
            file_data = request.FILES['file']
            
            # Validate file content or size before processing
            if not file_data.name.endswith(('.txt', '.pdf')) or file_data.size > 10 * 1024 * 1024:
                raise ValidationFailed("Invalid or too large file")
            
            # Process the upload
            processed_data = process_file(file_data)
            
            return Response(processed_data)
    
        except Exception as e:
            logger.error(f"Error during file upload: {str(e)}")
            return JsonResponse({'error': 'An internal server error occurred'}, status=HTTP_500_INTERNAL_SERVER_ERROR)

This revised version separates concerns logically and adds basic input validation to handle file uploads appropriately. Make sure to adjust function arguments based on your specific model structures and requirements.

meta = {'debug': True}
file_id = meta.get('file_id', uuid.uuid1())
file = File(id=file_id, file_name=self.data.get('file').name, meta=meta)
file.save(self.data.get('file').read())
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks generally correct, but there are a couple of improvements that can be made:

  1. Null Check: Ensure that self.data is not null before accessing get('file'). This prevents potential errors if no file is uploaded.

  2. File Handling: Use TemporaryFileStorage or the appropriate storage backend (e.g., S3) to handle files instead of storing them directly into the database. Storing files in memory can lead to high memory usage and slow performance.

Here's an optimized version of the method:

from django.core.files.storage import FileSystemStorage

class FileSerializer(serializers.Serializer):
    def upload(self, with_valid=True):
        if with_valid:
            self.is_valid(raise_exception=True)

        # Get metadata
        meta = {}
        if 'meta' in self.data:
            meta.update(self.data['meta'])

        # Set default debug setting
        meta.setdefault('debug', True)

        file_id = meta.get('file_id', uuid.uuid4().hex)
        # Create a temporary file object
        temp_file = tempfile.NamedTemporaryFile(delete=False)
        temp_file.write(self.data.get('file').read())

        try:
            # Save the file using Django's FileField API
            file_object = FileSystemStorage(location=str(settings.MEDIA_ROOT)).save(file_name=temp_file.name.split('/')[-1], content=temp_file)
            
            # Create or update the existing File entry
            File.objects.update_or_create(
                id=file_id,
                defaults={
                    'file_name': os.path.basename(temp_file.name),
                    'meta': meta,
                }
            )
        finally:
            # Clean up the temporary file after saving it
            temp_file.close()
            os.unlink(temp_file.name)  # Remove the physical file
            

Key Changes:

  • Added null checks for self.data.
  • Used tempfile.NamedTemporaryFile() to avoid holding the entire file in memory.
  • Utilized Django's FileSystemStorage to manage file storage efficiently, leveraging its built-in caching features.
  • Ensured clean-up of the temporary file after processing, preventing file leaks on server restarts.
  • Provided a more robust error handling mechanism by closing and removing the temporary file even during exceptions.

This approach avoids direct database interaction with binary data, making it more efficient both from performance and resource management perspectives.

@liuruibin liuruibin merged commit dd84da4 into main Feb 28, 2025
4 checks passed
@liuruibin liuruibin deleted the pr@main@fix_swagger branch February 28, 2025 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants