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

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)
]