- Recipe model with ingredients (amount/range, unit, group, note), steps, lowercase tags, author notes, source URL and private/public visibility - Central RecipeQuerySet.visible_to() used by every read path; edit only by owner, delete by owner or admin (visible recipes only) - Text-based editing: ingredient/step parser with roundtrip and scaling - Photo upload (JPEG/PNG/WebP/HEIC), re-encoded to WebP without EXIF, thumbnails, cover image, served only through permission-checked view - Search across title, description, ingredients, tags; ingredient and tag filters; "mine" and favourites views - Admin can delete all recipes of a deactivated user - Acceptance tests: private recipes unreachable for others and admins in list, search, tags, favourites, detail, edit, delete and image URLs Co-Authored-By: Claude Opus 5.5 <[email protected]>
27 lines
789 B
Python
27 lines
789 B
Python
from django.contrib.auth.decorators import login_not_required
|
|
from django.db import connection
|
|
from django.http import JsonResponse
|
|
from django.shortcuts import render
|
|
from django.views.decorators.cache import never_cache
|
|
from django.views.decorators.http import require_GET
|
|
|
|
|
|
@login_not_required
|
|
@never_cache
|
|
@require_GET
|
|
def healthz(request):
|
|
try:
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("SELECT 1")
|
|
except Exception:
|
|
return JsonResponse({"status": "error", "database": "unreachable"}, status=503)
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
def error_403(request, exception=None):
|
|
return render(request, "errors/403.html", status=403)
|
|
|
|
|
|
def error_404(request, exception=None):
|
|
return render(request, "errors/404.html", status=404)
|