Menu
CoddyTech

מחלקה אחת לכל משאב

חלק מהיחידה ממשקי API של JSON במסלול ה-Django של Coddy. שיעור 11 מתוך 19.

task_detail היא כעת שרשרת של בלוקי if request.method == ... בתוספת רשימת שיטות שצריך לשמור על התאמה ביניהן. מחלקת הבסיס של Django, View, שנמצאת מתחת לכל תצוגה גנרית שבה השתמשת, מנהלת את הרישום הזה.

תני למחלקה שיטה אחת לכל שיטת HTTP, בשם באותיות קטנות. View קוראת לשיטה ששמה תואם לבקשה ומשיבה 405 לכל בקשה אחרת. ערכים מכתובת ה-URL מגיעים אחרי request, כמו בתצוגת פונקציה, והנתיב משתמש ב-.as_view(). כאן המשאב הוא ערכת הצבעים של המבקר, שנשמרת בהפעלה:

from django.utils.decorators import method_decorator
from django.views import View

@method_decorator(csrf_exempt, name="dispatch")
class Theme(View):
    def get(self, request):
        return JsonResponse({"theme": request.session.get("theme", "light")})

    def put(self, request):
        data = json.loads(request.body)
        request.session["theme"] = data["theme"]
        return JsonResponse({"theme": data["theme"]})

@csrf_exempt פועל על פונקציות. במחלקה, method_decorator מחיל אותו על dispatch, השיטה שכל בקשה עוברת דרכה.

challenge icon

אתגר

בינוני

הפכו את task_detail למחלקה.

  1. ב־tasks/views.py, ייבאו את View מתוך django.views ואת method_decorator מתוך django.utils.decorators.
  2. החליפו את הפונקציה ואת שתי הדקורטורים ב־class TaskDetail(View). המתודות get, patch ו־delete מקבלות את (self, request, pk), וכל אחת מבצעת את העבודה של הענף המקביל הישן שלה.
  3. החריגו את המחלקה מ־CSRF על ידי הצבת method_decorator(csrf_exempt) על dispatch.
  4. ב־tasks/urls.py, נווטו אל views.TaskDetail.as_view(), כשהשם נשאר task_detail.

פתחו את /api/tasks/1/: Buy milk מופיעה כ־JSON.

נסו בעצמכם

import json

from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_http_methods

from .models import Task


def task_to_dict(task):
    return {
        "id": task.id,
        "title": task.title,
        "done": task.done,
        "priority": task.priority,
    }


def home(request):
    return render(request, "tasks/home.html", {"tasks": Task.objects.all()})


@require_GET
def stats(request):
    data = {
        "total": Task.objects.count(),
        "done": Task.objects.filter(done=True).count(),
    }
    return JsonResponse(data)


@csrf_exempt
@require_http_methods(["GET", "POST"])
def task_list(request):
    if request.method == "POST":
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({"error": "The body is not valid JSON."}, status=400)
        errors = {}
        title = data.get("title", "").strip()
        if not title:
            errors["title"] = "This field is required."
        if errors:
            return JsonResponse({"errors": errors}, status=400)
        task = Task.objects.create(
            title=title,
            priority=data.get("priority", "normal"),
        )
        return JsonResponse(task_to_dict(task), status=201)
    tasks = Task.objects.all()
    done = request.GET.get("done")
    if done == "true":
        tasks = tasks.filter(done=True)
    elif done == "false":
        tasks = tasks.filter(done=False)
    return JsonResponse([task_to_dict(task) for task in tasks], safe=False)


@csrf_exempt
@require_http_methods(["GET", "PATCH", "DELETE"])
def task_detail(request, pk):
    task = Task.objects.filter(pk=pk).first()
    if task is None:
        return JsonResponse({"error": "Task not found"}, status=404)
    if request.method == "DELETE":
        task.delete()
        return HttpResponse(status=204)
    if request.method == "PATCH":
        data = json.loads(request.body)
        if "title" in data:
            task.title = data["title"]
        if "done" in data:
            task.done = data["done"]
        task.save()
    return JsonResponse(task_to_dict(task))
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה ממשקי API של JSON

תרגלו בעצמכם: Django אונליין