REST API CRUD with DJANGO

First is setup django with install the requirements py -m venv venv venv/Scripts/activate pip install django django-admin startproject myproject cd myproject python manage.py startapp members requirement.py pip install -r requirements.txt. asgiref==3.8.1 blinker==1.9.0 click==8.1.8 colorama==0.4.6 Django==5.1.7 django-cors-headers==4.7.0 Flask==3.1.0 flask-cors==5.0.1 Flask-SQLAlchemy==3.1.1 greenlet==3.1.1 itsdangerous==2.2.0 Jinja2==3.1.6 MarkupSafe==3.0.2 setuptools==76.0.0 SQLAlchemy==2.0.38 sqlparse==0.5.3 typing_extensions==4.12.2 tzdata==2025.1 Werkzeug==3.1.3 wheel==0.45.1t # views.py from base64 import b64encode import uuid from django.http import JsonResponse from rest_framework import viewsets,status from rest_framework.response import Response from rest_framework.permissions import AllowAny , IsAuthenticated from restoApi import settings from .serializer import * from rest_framework.views import APIView from .models import * import requests class LoginViewSet(viewsets.ViewSet): permission_classes=[AllowAny] def create(self,req): serializer = LoginSerializer(data=req.data) if serializer.is_valid(): return Response(serializer.validated_data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class ReservasiViewSet(viewsets.ModelViewSet): queryset=Reservasi.objects.all() serializer_class = ReservasiSerializer permission_classes = [IsAuthenticated] def perform_create(self, serializer): serializer.save(id_admin = self.request.user) class MenuViewSet(viewsets.ModelViewSet): permission_classes=[IsAuthenticated] queryset=Menu.objects.all() serializer_class= MenuSerializer class MejaViewSet(viewsets.ModelViewSet): permission_classes=[IsAuthenticated] queryset=Meja.objects.all() serializer_class= MejaSerializer class TransaksiViewSet(viewsets.ModelViewSet): permission_classes=[IsAuthenticated] queryset=Transaksi.objects.all() serializer_class= TransaksiSerializer class TransaksiDetailViewSet(viewsets.ModelViewSet): permission_classes=[IsAuthenticated] queryset=TransaksiDetail.objects.all() serializer_class= TransaksiDetailSerializer def buat_transaksi(request,id_reservasi): try: reservasi = Reservasi.objects.get(pk=id_reservasi) # Contoh hitung grand total total_harga = reservasi.total_harga # bisa ambil dari reservasi ppn = total_harga * 0.1 diskon = 5000 grand_total = total_harga + ppn - diskon transaksi = Transaksi.objects.create( id_reservasi=reservasi, total_harga=total_harga, ppn=ppn, diskon=diskon, grand_total=grand_total, status_pembayaran='pending' ) order_id = f"TRX-{transaksi.id_transaksi}" # Midtrans Auth Header server_key = settings.MIDTRANS_SERVER_KEY base64_auth = b64encode(f"{server_key}:".encode()).decode() headers = { "Accept": "application/json", "Content-Type": "application/json", "Authorization": f"Basic {base64_auth}" } data = { "transaction_details": { "order_id": order_id, "gross_amount": int(grand_total), }, "customer_details": { "first_name": "Customer", "last_name": "Test", "email": "test@example.com", "phone": "08123456789" } } response = requests.post( settings.MIDTRANS_SNAP_URL, headers=headers, json=data ) res_data = response.json() return JsonResponse({ "token": res_data.get("token"), "redirect_url": res_data.get("redirect_url"), "order_id": order_id }) except Reservasi.DoesNotExist: return JsonResponse({"error": "Reservasi tidak ditemukan"}, status=404) # models.py from django.db import models from django.contrib.auth.models import User class Meja(models.Model): id_meja = models.AutoField(primary_key=True) no_meja = models.CharField(unique=True, max_length=100) kapasitas = models.IntegerField() image_meja = models.ImageField(upload_to="assets/meja/",null=True,blank=True) class Meta: db_table = 'meja' class Menu(models.Model): id_menu = models.AutoField(primary_key=True) nama_menu = models.CharField(max_length=100) harga = models.DecimalField(max_digits=10, decimal_places=0) id_kategori = models.ForeignKey('MenuKategori', models.DO_NOTHING, db_column='id_kategori') menu_image = models.ImageField(upload_to="assets/", null=True, blank=True) class Meta: db_table = 'menu' class MenuKategori(models.Model): id_kategori = models.AutoField(primary_key=Tru

Apr 7, 2025 - 15:20
 0
REST API CRUD with DJANGO

First is setup django with install the requirements


py -m venv venv

venv/Scripts/activate

pip install django

django-admin startproject myproject

cd myproject

python manage.py startapp members


requirement.py

pip install -r requirements.txt.

asgiref==3.8.1
blinker==1.9.0
click==8.1.8
colorama==0.4.6
Django==5.1.7
django-cors-headers==4.7.0
Flask==3.1.0
flask-cors==5.0.1
Flask-SQLAlchemy==3.1.1
greenlet==3.1.1
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
setuptools==76.0.0
SQLAlchemy==2.0.38
sqlparse==0.5.3
typing_extensions==4.12.2
tzdata==2025.1
Werkzeug==3.1.3
wheel==0.45.1t

# views.py


from base64 import b64encode
import uuid

from django.http import JsonResponse
from rest_framework import viewsets,status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny , IsAuthenticated
from restoApi import settings
from .serializer import *
from rest_framework.views import APIView
from .models import *
import requests


class LoginViewSet(viewsets.ViewSet):
    permission_classes=[AllowAny]

    def create(self,req):
        serializer = LoginSerializer(data=req.data)
        if serializer.is_valid():
            return Response(serializer.validated_data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class ReservasiViewSet(viewsets.ModelViewSet):
    queryset=Reservasi.objects.all()
    serializer_class = ReservasiSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(id_admin = self.request.user)

class MenuViewSet(viewsets.ModelViewSet):
    permission_classes=[IsAuthenticated]        
    queryset=Menu.objects.all()
    serializer_class= MenuSerializer


class MejaViewSet(viewsets.ModelViewSet):
    permission_classes=[IsAuthenticated]        
    queryset=Meja.objects.all()
    serializer_class= MejaSerializer



class TransaksiViewSet(viewsets.ModelViewSet):
    permission_classes=[IsAuthenticated]    
    queryset=Transaksi.objects.all()
    serializer_class= TransaksiSerializer

class TransaksiDetailViewSet(viewsets.ModelViewSet):
    permission_classes=[IsAuthenticated]    
    queryset=TransaksiDetail.objects.all()
    serializer_class= TransaksiDetailSerializer

def buat_transaksi(request,id_reservasi):
    try:
        reservasi = Reservasi.objects.get(pk=id_reservasi)

        # Contoh hitung grand total
        total_harga = reservasi.total_harga  # bisa ambil dari reservasi
        ppn = total_harga * 0.1

        diskon = 5000
        grand_total = total_harga + ppn - diskon

        transaksi = Transaksi.objects.create(
            id_reservasi=reservasi,
            total_harga=total_harga,
            ppn=ppn,
            diskon=diskon,
            grand_total=grand_total,
            status_pembayaran='pending'
        )

        order_id = f"TRX-{transaksi.id_transaksi}"

        # Midtrans Auth Header  
        server_key = settings.MIDTRANS_SERVER_KEY
        base64_auth = b64encode(f"{server_key}:".encode()).decode()

        headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": f"Basic {base64_auth}"
        }

        data = {
            "transaction_details": {
                "order_id": order_id,
                "gross_amount": int(grand_total),
            },
            "customer_details": {
                "first_name": "Customer",
                "last_name": "Test",    
                "email": "test@example.com",
                "phone": "08123456789"
            }
        }

        response = requests.post(
            settings.MIDTRANS_SNAP_URL,
            headers=headers,
            json=data
        )

        res_data = response.json()
        return JsonResponse({
            "token": res_data.get("token"),
            "redirect_url": res_data.get("redirect_url"),
            "order_id": order_id
        })

    except Reservasi.DoesNotExist:
        return JsonResponse({"error": "Reservasi tidak ditemukan"}, status=404)

# models.py

from django.db import models
from django.contrib.auth.models import User


class Meja(models.Model):
    id_meja = models.AutoField(primary_key=True)
    no_meja = models.CharField(unique=True, max_length=100)
    kapasitas = models.IntegerField()
    image_meja = models.ImageField(upload_to="assets/meja/",null=True,blank=True)

    class Meta:
        db_table = 'meja'


class Menu(models.Model):
    id_menu = models.AutoField(primary_key=True)
    nama_menu = models.CharField(max_length=100)
    harga = models.DecimalField(max_digits=10, decimal_places=0)
    id_kategori = models.ForeignKey('MenuKategori', models.DO_NOTHING, db_column='id_kategori')
    menu_image =  models.ImageField(upload_to="assets/", null=True, blank=True)

    class Meta:
        db_table = 'menu'


class MenuKategori(models.Model):
    id_kategori = models.AutoField(primary_key=True)
    nama_kategori = models.CharField(max_length=100)

    class Meta:     
        db_table = 'menu_kategori'


class Reservasi(models.Model):
    id_reservasi = models.AutoField(primary_key=True)
    id_meja = models.ForeignKey(Meja, models.DO_NOTHING, db_column='id_meja', blank=True, null=True)
    id_admin = models.ForeignKey(User, on_delete=models.CASCADE,db_column='id_admin',null=True)
    nama_customer = models.CharField(max_length=100)
    tanggal_reservasi = models.DateTimeField()
    status = models.CharField(max_length=100)

    class Meta:
        db_table = 'reservasi'


class Stok(models.Model):
    id_stok = models.AutoField(primary_key=True)
    id_menu = models.ForeignKey(Menu, models.DO_NOTHING, db_column='id_menu', blank=True, null=True)
    jumlah_stok = models.IntegerField(blank=True, null=True)

    class Meta:
        db_table = 'stok'


class Transaksi(models.Model):
    id_transaksi = models.AutoField(primary_key=True)
    id_reservasi = models.ForeignKey(Reservasi, models.DO_NOTHING, db_column='id_reservasi', blank=True, null=True)
    total_harga = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
    ppn = models.DecimalField(max_digits=10, decimal_places=0)
    diskon = models.DecimalField(max_digits=10, decimal_places=0)
    grand_total = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
    status_pembayaran = models.CharField(max_length=100, blank=True, null=True)

    class Meta:
        db_table = 'transaksi'


class TransaksiDetail(models.Model):
    id_detail = models.AutoField(primary_key=True)
    id_transaksi = models.ForeignKey(Transaksi, models.DO_NOTHING, db_column='id_transaksi', blank=True, null=True)
    id_menu = models.ForeignKey(Menu, models.DO_NOTHING, db_column='id_menu', blank=True, null=True)
    jumlah = models.IntegerField(blank=True, null=True)
    sub_total = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)

    class Meta:
        db_table = 'transaksi_detail'//

# serializer.py

from rest_framework import serializers
from .models import *
from rest_framework_simplejwt.tokens import  RefreshToken
from django.contrib.auth import authenticate


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email']

class LoginSerializer(serializers.Serializer):
    username=serializers.CharField()
    password = serializers.CharField(write_only=True)

    def validate(self, data):
        user = authenticate(username=data['username'],password=data['password'])
        if not user:
            raise serializers.ValidationError("Username atau Password tidak ditemukan")

        refresh =RefreshToken.for_user(user)
        return{
            'refresh': str(refresh),
            'access': str(refresh.access_token),
            'user':UserSerializer(user).data
        }

class ReservasiSerializer(serializers.ModelSerializer):
    class Meta:
        model = Reservasi
        fields = '__all__'

class MenuSerializer(serializers.ModelSerializer):
    class Meta:
        model = Menu
        fields = '__all__'

class TransaksiSerializer(serializers.ModelSerializer):
    class Meta:
        model = Transaksi
        fields = '__all__'

class MejaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Meja
        fields = '__all__'

class MenuKategoriSerializer(serializers.ModelSerializer):
    class Meta:
        model = MenuKategori
        fields = '__all__'

class StokSerializer(serializers.ModelSerializer):
    class Meta:
        model = Stok
        fields = '__all__'

class TransaksiDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = TransaksiDetail
        fields = '__all__'

class ReservasiDetailSerializer(serializers.ModelSerializer):
    meja = MejaSerializer()
    class Meta:
        model = Reservasi
        fields = '__all__'
# settings

"""
Django settings for restoApi project.

Generated by 'django-admin startproject' using Django 5.2.

For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""

from datetime import timedelta
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'SECRET'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'yourApp',
    'rest_framework',
    'rest_framework_simplejwt',
    "corsheaders"
]
SIMPLE_JWT={    
    "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
    "SLIDING_TOKEN_LIFETIME": timedelta(hours=7),
    "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
    "ACCESS_TOKEN_LIFETIME": timedelta(hours=7),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
}
MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ALLOW_ALL_ORIGIN= True
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
]
ROOT_URLCONF = 'restoApi.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'restoApi.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'yourdb',
        'USER' : 'root',
        'PASSWORD' : '',
        'HOST' : 'localhost',
        'PORT' : '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'"
        }
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MIDTRANS_SERVER_KEY = 'SECRET'
MIDTRANS_CLIENT_KEY = 'SECRET'
MIDTRANS_SNAP_URL = 'https://app.sandbox.midtrans.com/snap/v1/transactions'

MEDIA_URL ='/'
MEDIA_ROOT = BASE_DIR
#url (project)
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static

from restoApi import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/',include('restoApp.urls'))
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)



# url (app)

from rest_framework.routers import DefaultRouter
from .views import *
from django.urls import path,include

router = DefaultRouter()
router.register(r'login',LoginViewSet,basename='login')
router.register(r'reservasi',ReservasiViewSet,basename='reservasi')
router.register(r'menu',MenuViewSet,basename='menu')
router.register(r'transaksi',TransaksiViewSet   ,basename='transaksi')
router.register(r'meja',MejaViewSet,basename ='meja')
router.register(r'transaksidetail',TransaksiDetailViewSet,basename ='transaksidetail')

urlpatterns = [
    path('',include(router.urls)),
    path('bayar/', buat_transaksi)

]