search
LoginSignup
0

posted at

updated at

Organization

Drag And Drop with Django Rest API【Python】

Assumption

django rest_api has been created

Introduction

Created API for dragging and dropping category models.

Flow

  • Assign an index if one is not allocated when getting a Category
  • Assign an index when creating a Category
  • Update the index value of Category

Setup

Create django app

$ python manage.py startapp category

setting.py

INSTALLED_APPS = [
    .
    .
    .
    'category',
]

Coding

models.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=32, blank=False, null=False)
    index = models.IntegerField(blank=True, null=True)
    image = models.TextField(blank=True, null=True)
    user_id = models.IntegerField(blank=False, null=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

serializers.py

from django.db.models import fields
from rest_framework import serializers
from category.models import Category


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__

urls.py

from django.urls import path
from category import views

urlpatterns = [
    path("", views.category_list, name="category-list"),
    path("<int:pk>/", views.category_detail, name="category-detail"),
    path("drag_and_drop/", views.category_drag_and_drop, name="category-drag-and-drop"),
]

views.py

from django.http.response import JsonResponse
from category.models import Category
from category.serializers import CategorySerializer
from deep_log_api.auth import JWTAuthentication
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404, render

def null_check(number):
    if number == None:
      return False
    return True

def has_duplicates(seq):
    return len(seq) != len(set(seq))

@api_view(['GET', 'POST'])
@authentication_classes([JWTAuthentication, ])
@permission_classes([IsAuthenticated, ])
def category_list(request):
    if request.method == 'GET':
        categories = Category.objects.filter(user_id=request.user.id)
        for i, category in enumerate(categories):
            category_indices = Category.objects.filter(user_id=request.user.id).values_list('index', flat=True)
            if category.index == None or has_duplicates(category_indices):
                new_category = {
                    "name": category.name,
                    "user_id": category.user_id,
                    "index": 0 if i == 0 else max(filter(null_check, category_indices)) + 1,
                    "image": category.image,
                }
                serializer = CategorySerializer(category, data=new_category)
                if serializer.is_valid():
                    serializer.save()
        
        categories_have_index = Category.objects.filter(user_id=request.user.id).order_by('index')
        serializer = CategorySerializer(categories_have_index, many=True)
        response = Response(serializer.data)
        return response

    if request.method == 'POST':
        category_indices = Category.objects.filter(user_id=request.user.id).values_list('index', flat=True)
        
        def get_image():
            try:
                return request.data["image"]
            except:
                return ''
        
        new_category = {
            "name": request.data["name"],
            "user_id": request.user.id,
            "index": 0 if len(category_indices) == 0 else max(filter(null_check, category_indices)) + 1,
            "image": get_image(),
        }
        serializer = CategorySerializer(data=new_category)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'DELETE'])
@authentication_classes([JWTAuthentication, ])
@permission_classes([IsAuthenticated, ])
def category_detail(request, pk):
    try:
        category = Category.objects.get(pk=pk)
    except Category.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = CategorySerializer(category)
        return Response(serializer.data)

    if request.method == 'PUT':
        def get_image():
            try:
                return request.data["image"]
            except:
                return category.image
        
        new_category = {
            "name": request.data["name"],
            "user_id": request.user.id,
            "index": category.index,
            "image": get_image(),
        }
        serializer = CategorySerializer(category, data=new_category)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'DELETE':
        category.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


@api_view(['PUT'])
@authentication_classes([JWTAuthentication, ])
@permission_classes([IsAuthenticated, ])
def category_drag_and_drop(request):
    if request.method == 'PUT':
        source = Category.objects.get(id=request.data["source_id"])
        target = Category.objects.get(id=request.data["target_id"])
        update_source = Category.objects.get(id=request.data["source_id"])
        update_target = Category.objects.get(id=request.data["target_id"])

        update_source.index = target.index
        update_target.index = source.index

        update_source.save()
        update_target.save()

        return Response(status=status.HTTP_204_NO_CONTENT)

Run

image.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0