From 53181c750a913547f9606dcbbad78e25b2071a7e Mon Sep 17 00:00:00 2001 From: Devoalda Date: Mon, 23 Oct 2023 12:12:25 +0800 Subject: [PATCH] feature(Cache Storage): CRUD using Redis and Django API --- safeshare.http | 1 + safeshare/safeshare/settings.py | 22 ++-- safeshare/safeshare/urls.py | 3 +- .../safeshare_app/migrations/0001_initial.py | 22 ++++ safeshare/safeshare_app/models.py | 3 - safeshare/safeshare_app/models/__init__.py | 0 safeshare/safeshare_app/models/file.py | 25 ++++ .../safeshare_app/serializers/__init__.py | 0 safeshare/safeshare_app/serializers/file.py | 7 + safeshare/safeshare_app/tests.py | 3 - safeshare/safeshare_app/urls/__init__.py | 11 ++ safeshare/safeshare_app/views.py | 3 - safeshare/safeshare_app/views/__init__.py | 1 + safeshare/safeshare_app/views/file.py | 120 ++++++++++++++++++ 14 files changed, 201 insertions(+), 20 deletions(-) create mode 100644 safeshare.http create mode 100644 safeshare/safeshare_app/migrations/0001_initial.py delete mode 100644 safeshare/safeshare_app/models.py create mode 100644 safeshare/safeshare_app/models/__init__.py create mode 100644 safeshare/safeshare_app/models/file.py create mode 100644 safeshare/safeshare_app/serializers/__init__.py create mode 100644 safeshare/safeshare_app/serializers/file.py delete mode 100644 safeshare/safeshare_app/tests.py create mode 100644 safeshare/safeshare_app/urls/__init__.py delete mode 100644 safeshare/safeshare_app/views.py create mode 100644 safeshare/safeshare_app/views/__init__.py create mode 100644 safeshare/safeshare_app/views/file.py diff --git a/safeshare.http b/safeshare.http new file mode 100644 index 0000000..f1c00ae --- /dev/null +++ b/safeshare.http @@ -0,0 +1 @@ +GET localhost:8000/api/files?b10a53f-5bd7-4988-a6c2-564edbcb7dfb diff --git a/safeshare/safeshare/settings.py b/safeshare/safeshare/settings.py index b9f9d15..156dd82 100644 --- a/safeshare/safeshare/settings.py +++ b/safeshare/safeshare/settings.py @@ -36,6 +36,8 @@ DEBUG = env('DEBUG', default=False) ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['*']) +REDIS_HOST = env.str('REDIS_HOST', default='localhost') +REDIS_PORT = env.str('REDIS_PORT', default='6379') # Application definition @@ -65,16 +67,16 @@ MIDDLEWARE = [ ROOT_URLCONF = 'safeshare.urls' -REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework_simplejwt.authentication.JWTAuthentication', - 'rest_framework.authentication.SessionAuthentication', - 'rest_framework.authentication.BasicAuthentication', - ), -} +# REST_FRAMEWORK = { +# 'DEFAULT_PERMISSION_CLASSES': ( +# 'rest_framework.permissions.IsAuthenticated', +# ), +# 'DEFAULT_AUTHENTICATION_CLASSES': ( +# 'rest_framework_simplejwt.authentication.JWTAuthentication', +# 'rest_framework.authentication.SessionAuthentication', +# 'rest_framework.authentication.BasicAuthentication', +# ), +# } SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=10), 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), diff --git a/safeshare/safeshare/urls.py b/safeshare/safeshare/urls.py index 6c27924..199c753 100644 --- a/safeshare/safeshare/urls.py +++ b/safeshare/safeshare/urls.py @@ -15,8 +15,9 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), + path('api/', include('safeshare_app.urls')), ] diff --git a/safeshare/safeshare_app/migrations/0001_initial.py b/safeshare/safeshare_app/migrations/0001_initial.py new file mode 100644 index 0000000..ed1ce70 --- /dev/null +++ b/safeshare/safeshare_app/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.5 on 2023-10-23 03:37 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='File', + fields=[ + ('key', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('value', models.BinaryField()), + ], + ), + ] diff --git a/safeshare/safeshare_app/models.py b/safeshare/safeshare_app/models.py deleted file mode 100644 index 71a8362..0000000 --- a/safeshare/safeshare_app/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/safeshare/safeshare_app/models/__init__.py b/safeshare/safeshare_app/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/safeshare/safeshare_app/models/file.py b/safeshare/safeshare_app/models/file.py new file mode 100644 index 0000000..07a6837 --- /dev/null +++ b/safeshare/safeshare_app/models/file.py @@ -0,0 +1,25 @@ +# import uuid +# +# from django.db import models +# from django.core.cache import cache +# +# +# class File(models.Model): +# key = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) +# value = models.BinaryField() +# +# REQUIRED_FIELDS = ['value'] +# +# def __str__(self): +# return self.key +# +# @classmethod +# def get_or_set(cls, key, value=None, timeout=None): +# data = cache.get(str(key)) +# +# if data is None: +# data = value +# +# cache.set(str(key), data, timeout=timeout) +# +# return data diff --git a/safeshare/safeshare_app/serializers/__init__.py b/safeshare/safeshare_app/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/safeshare/safeshare_app/serializers/file.py b/safeshare/safeshare_app/serializers/file.py new file mode 100644 index 0000000..0127e91 --- /dev/null +++ b/safeshare/safeshare_app/serializers/file.py @@ -0,0 +1,7 @@ +# from rest_framework import serializers +# from safeshare_app.models import File +# +# class FileSerializer(serializers.ModelSerializer): +# class Meta: +# model = File +# fields = ('key', 'value') diff --git a/safeshare/safeshare_app/tests.py b/safeshare/safeshare_app/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/safeshare/safeshare_app/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/safeshare/safeshare_app/urls/__init__.py b/safeshare/safeshare_app/urls/__init__.py new file mode 100644 index 0000000..243ec81 --- /dev/null +++ b/safeshare/safeshare_app/urls/__init__.py @@ -0,0 +1,11 @@ +from django.urls import path, include +from rest_framework import routers +from safeshare_app.views import manage_items, manage_item + +# router = routers.SimpleRouter() +# router.register(r'files', FileView, basename='file') + +urlpatterns = [ + path('files/', manage_items, name="manage_items"), + path('files//', manage_item, name="manage_item"), +] diff --git a/safeshare/safeshare_app/views.py b/safeshare/safeshare_app/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/safeshare/safeshare_app/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/safeshare/safeshare_app/views/__init__.py b/safeshare/safeshare_app/views/__init__.py new file mode 100644 index 0000000..1082199 --- /dev/null +++ b/safeshare/safeshare_app/views/__init__.py @@ -0,0 +1 @@ +from .file import * \ No newline at end of file diff --git a/safeshare/safeshare_app/views/file.py b/safeshare/safeshare_app/views/file.py new file mode 100644 index 0000000..18b2460 --- /dev/null +++ b/safeshare/safeshare_app/views/file.py @@ -0,0 +1,120 @@ +import json +from django.conf import settings +import redis +import base64 +import uuid +from rest_framework.decorators import api_view +from rest_framework import status +from rest_framework.response import Response + +# from safeshare_app.models.file import File +# from safeshare_app.serializers.file import FileSerializer + +redis_instance = redis.StrictRedis(host=settings.REDIS_HOST, + port=settings.REDIS_PORT, db=0) + + +@api_view(['GET', 'POST']) +def manage_items(request, *args, **kwargs): + if request.method == 'GET': + items = {} + count = 0 + for key in redis_instance.keys("*"): + items[key.decode("utf-8")] = redis_instance.get(key) + count += 1 + response = { + 'count': count, + 'msg': f"Found {count} items.", + 'items': items + } + return Response(response, status=200) + if request.method == 'POST': + item = json.loads(request.body) + key = uuid.uuid4().hex + value = item['value'] + + # Modify value to binary object (base64) + value = base64.b64encode(value.encode('utf-8')) + redis_instance.set(key, value) + response = { + 'msg': f"{key} successfully set to {value}" + } + return Response(response, 201) + + +@api_view(['GET', 'PUT', 'DELETE']) +def manage_item(request, *args, **kwargs): + if request.method == 'GET': + if kwargs['key']: + value = redis_instance.get(kwargs['key']) + if value: + response = { + 'key': kwargs['key'], + 'value': value, + 'msg': 'success' + } + return Response(response, status=200) + else: + response = { + 'key': kwargs['key'], + 'value': None, + 'msg': 'Not found' + } + return Response(response, status=404) + elif request.method == 'PUT': + if kwargs['key']: + request_data = json.loads(request.body) + new_value = request_data['new_value'] + value = redis_instance.get(kwargs['key']) + if value: + redis_instance.set(kwargs['key'], new_value) + response = { + 'key': kwargs['key'], + 'value': value, + 'msg': f"Successfully updated {kwargs['key']}" + } + return Response(response, status=200) + else: + response = { + 'key': kwargs['key'], + 'value': None, + 'msg': 'Not found' + } + return Response(response, status=404) + + elif request.method == 'DELETE': + if kwargs['key']: + result = redis_instance.delete(kwargs['key']) + if result == 1: + response = { + 'msg': f"{kwargs['key']} successfully deleted" + } + return Response(response, status=404) + else: + response = { + 'key': kwargs['key'], + 'value': None, + 'msg': 'Not found' + } + return Response(response, status=404) + +# class FileView(viewsets.ModelViewSet): +# queryset = File.objects.all() +# serializer_class = FileSerializer +# permission_classes = () +# +# def get_queryset(self): +# # Only allow GET with a key +# key = self.request.query_params.get('key', None) +# if key is not None: +# # Remove / from end of key +# if key[-1] == '/': +# key = key[:-1] +# +# print(key) +# data = self.queryset.filter(key=key) +# return data +# +# else: +# # Return nothing if no key is provided +# return File.objects.none()