LoginSignup
0
0

More than 1 year has passed since last update.

Drag And Drop with Django Rest API【Python】

Last updated at Posted at 2022-04-22

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

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0