feat: Refactor rides app with unique constraints, mixins, and enhanced documentation

- Added migration to convert unique_together constraints to UniqueConstraint for RideModel.
- Introduced RideFormMixin for handling entity suggestions in ride forms.
- Created comprehensive code standards documentation outlining formatting, docstring requirements, complexity guidelines, and testing requirements.
- Established error handling guidelines with a structured exception hierarchy and best practices for API and view error handling.
- Documented view pattern guidelines, emphasizing the use of CBVs, FBVs, and ViewSets with examples.
- Implemented a benchmarking script for query performance analysis and optimization.
- Developed security documentation detailing measures, configurations, and a security checklist.
- Compiled a database optimization guide covering indexing strategies, query optimization patterns, and computed fields.
This commit is contained in:
pacnpal
2025-12-22 11:17:31 -05:00
parent 45d97b6e68
commit 2e35f8c5d9
71 changed files with 8036 additions and 1462 deletions

View File

@@ -0,0 +1,219 @@
# Error Handling Guidelines
This document provides guidelines for handling errors consistently across the ThrillWiki backend.
## Exception Hierarchy
ThrillWiki uses a structured exception hierarchy defined in `apps/core/exceptions.py`:
```
ThrillWikiException (base)
├── ValidationException (400)
├── NotFoundError (404)
├── PermissionDeniedError (403)
├── BusinessLogicError (400)
├── ServiceError (500)
├── ExternalServiceError (502)
├── CacheError (500)
├── Domain-specific exceptions:
│ ├── ParkError
│ │ ├── ParkNotFoundError
│ │ └── ParkOperationError
│ ├── RideError
│ │ ├── RideNotFoundError
│ │ └── RideOperationError
│ ├── LocationError
│ │ ├── InvalidCoordinatesError
│ │ └── GeolocationError
│ ├── ReviewError
│ │ ├── ReviewModerationError
│ │ └── DuplicateReviewError
│ └── AccountError
│ ├── InsufficientPermissionsError
│ └── EmailError
```
## Using ErrorHandler
The `ErrorHandler` class in `apps/core/utils/error_handling.py` provides standardized error handling.
### Template Views
```python
from apps.core.utils.error_handling import ErrorHandler
from apps.core.exceptions import ServiceError
def my_view(request):
try:
result = SomeService.do_operation(...)
except ServiceError as e:
ErrorHandler.handle_view_error(
request,
e,
user_message="The operation failed. Please try again.",
log_message=f"Service operation failed for user {request.user.id}"
)
return redirect("some-fallback")
except ValidationError as e:
ErrorHandler.handle_view_error(
request,
e,
user_message="Invalid data provided",
level="warning"
)
return redirect("form-view")
```
### API Views
```python
from apps.core.utils.error_handling import ErrorHandler
from apps.core.exceptions import ServiceError
from rest_framework import status
class MyAPIView(APIView):
def post(self, request):
try:
result = SomeService.do_operation(...)
return ErrorHandler.api_success_response(
data=result,
message="Operation completed successfully"
)
except ServiceError as e:
return ErrorHandler.handle_api_error(
e,
user_message="Failed to complete operation",
status_code=status.HTTP_400_BAD_REQUEST
)
```
## Best Practices
### 1. Always Catch Specific Exceptions
```python
# Good
try:
park = ParkService.create_park(...)
except ParkOperationError as e:
# Handle park-specific error
pass
except ValidationException as e:
# Handle validation error
pass
# Bad
try:
park = ParkService.create_park(...)
except Exception as e:
# Too broad - loses error context
pass
```
### 2. Log with Appropriate Context
```python
# Good
logger.error(
f"Park creation failed for user {user.id}: {error}",
exc_info=True,
extra={"user_id": user.id, "park_name": name}
)
# Bad
logger.error(f"Error: {error}")
```
### 3. Provide Clear User Messages
```python
# Good - User-friendly and actionable
ErrorHandler.handle_view_error(
request,
error,
user_message="Unable to save your changes. Please check your input and try again."
)
# Bad - Technical details exposed to user
ErrorHandler.handle_view_error(
request,
error,
user_message=f"IntegrityError: UNIQUE constraint failed: parks_park.slug"
)
```
### 4. Use Appropriate HTTP Status Codes
| Error Type | Status Code | When to Use |
|------------|-------------|-------------|
| ValidationException | 400 | Invalid user input |
| NotFoundError | 404 | Resource doesn't exist |
| PermissionDeniedError | 403 | User lacks permission |
| BusinessLogicError | 400 | Business rule violation |
| ServiceError | 500 | Internal service failure |
| ExternalServiceError | 502 | Third-party service failure |
### 5. Never Use Bare `except:` Clauses
```python
# Never do this
try:
something()
except:
pass
# Always specify exception type
try:
something()
except SpecificException:
handle_error()
```
## Error Response Format
### API Error Response
```json
{
"error": "User-friendly error message",
"detail": "Technical error details",
"error_code": "SPECIFIC_ERROR_CODE",
"details": {
"field": "Additional context"
}
}
```
### API Success Response
```json
{
"status": "success",
"message": "Operation completed successfully",
"data": {
// Response data
}
}
```
## Creating Custom Exceptions
When creating domain-specific exceptions:
```python
from apps.core.exceptions import BusinessLogicError
class MyDomainError(BusinessLogicError):
"""Raised when my domain operation fails."""
default_message = "My domain operation failed"
error_code = "MY_DOMAIN_ERROR"
status_code = 400
def __init__(self, context_value: str = None, **kwargs):
if context_value:
kwargs["details"] = {"context": context_value}
kwargs["message"] = f"Operation failed for: {context_value}"
super().__init__(**kwargs)
```