권주희

Merge branch 'feature/item_api' into 'develop'

Feature/item api



See merge request !4
1 +# Generated by Django 3.0.6 on 2020-06-06 08:17
2 +
3 +from django.db import migrations
4 +
5 +
6 +class Migration(migrations.Migration):
7 +
8 + dependencies = [
9 + ('api', '0002_auto_20200605_1851'),
10 + ]
11 +
12 + operations = [
13 + migrations.RenameField(
14 + model_name='shareditem',
15 + old_name='valid',
16 + new_name='expires',
17 + ),
18 + ]
1 +# Generated by Django 3.0.6 on 2020-06-06 08:24
2 +
3 +from django.db import migrations, models
4 +
5 +
6 +class Migration(migrations.Migration):
7 +
8 + dependencies = [
9 + ('api', '0003_auto_20200606_0817'),
10 + ]
11 +
12 + operations = [
13 + migrations.AddField(
14 + model_name='shareditem',
15 + name='created_time',
16 + field=models.DateTimeField(auto_now=True),
17 + ),
18 + migrations.AddField(
19 + model_name='user',
20 + name='created_time',
21 + field=models.DateTimeField(auto_now=True),
22 + ),
23 + migrations.AlterField(
24 + model_name='item',
25 + name='created_time',
26 + field=models.DateTimeField(auto_now=True),
27 + ),
28 + ]
...@@ -11,7 +11,7 @@ class Item(models.Model): ...@@ -11,7 +11,7 @@ class Item(models.Model):
11 user_id = models.IntegerField() 11 user_id = models.IntegerField()
12 size = models.IntegerField() 12 size = models.IntegerField()
13 is_deleted = models.BooleanField(default = False) 13 is_deleted = models.BooleanField(default = False)
14 - created_time = models.DateTimeField(blank = False) 14 + created_time = models.DateTimeField(auto_now=True)
15 updated_time = models.DateTimeField() 15 updated_time = models.DateTimeField()
16 status = models.BooleanField() 16 status = models.BooleanField()
17 17
...@@ -24,9 +24,9 @@ class Item(models.Model): ...@@ -24,9 +24,9 @@ class Item(models.Model):
24 class SharedItem(models.Model): 24 class SharedItem(models.Model):
25 item_id = models.IntegerField() 25 item_id = models.IntegerField()
26 #file_id? 26 #file_id?
27 - valid = models.DateTimeField() 27 + expires = models.DateTimeField()
28 password = models.CharField(max_length = 20) 28 password = models.CharField(max_length = 20)
29 - 29 + created_time = models.DateTimeField(auto_now=True)
30 class Meta: 30 class Meta:
31 ordering = ['item_id'] 31 ordering = ['item_id']
32 32
...@@ -38,6 +38,6 @@ class User(models.Model): ...@@ -38,6 +38,6 @@ class User(models.Model):
38 password = models.CharField(max_length = 20) 38 password = models.CharField(max_length = 20)
39 total_size = models.IntegerField() 39 total_size = models.IntegerField()
40 current_size = models.IntegerField() 40 current_size = models.IntegerField()
41 - 41 + created_time = models.DateTimeField(auto_now=True)
42 class Meta: 42 class Meta:
43 ordering = ['int_id'] 43 ordering = ['int_id']
......
1 from django.contrib.auth.models import User, Group 1 from django.contrib.auth.models import User, Group
2 from rest_framework import serializers 2 from rest_framework import serializers
3 -from api.models import Item 3 +from api.models import Item, SharedItem
4 4
5 5
6 class UserSerializer(serializers.HyperlinkedModelSerializer): 6 class UserSerializer(serializers.HyperlinkedModelSerializer):
...@@ -17,3 +17,8 @@ class ItemSerializer(serializers.ModelSerializer): ...@@ -17,3 +17,8 @@ class ItemSerializer(serializers.ModelSerializer):
17 class Meta: 17 class Meta:
18 model = Item 18 model = Item
19 fields = '__all__' 19 fields = '__all__'
20 +
21 +class SharedItemSerializer(serializers.ModelSerializer):
22 + class Meta:
23 + model = Item
24 + fields = '__all__'
......
1 import mimetypes 1 import mimetypes
2 +import json
2 import os 3 import os
3 import boto3 4 import boto3
4 5
5 -from django.contrib.auth.models import User, Group 6 +from django.contrib.auth.models import User
6 -from django.http import HttpResponse, JsonResponse 7 +from django.core import serializers
8 +from django.views.decorators.csrf import csrf_exempt
7 from rest_framework import viewsets 9 from rest_framework import viewsets
8 from rest_framework import permissions 10 from rest_framework import permissions
9 -from django.views.decorators.csrf import csrf_exempt
10 -from rest_framework import renderers
11 from rest_framework.views import APIView 11 from rest_framework.views import APIView
12 from rest_framework.response import Response 12 from rest_framework.response import Response
13 from rest_framework.decorators import action 13 from rest_framework.decorators import action
14 from rest_framework.parsers import JSONParser 14 from rest_framework.parsers import JSONParser
15 from rest_framework.permissions import IsAuthenticated, AllowAny 15 from rest_framework.permissions import IsAuthenticated, AllowAny
16 16
17 -from api.models import Item 17 +from api.models import Item, SharedItem
18 -from api.serializers import UserSerializer,GroupSerializer,ItemSerializer 18 +from api.serializers import UserSerializer,GroupSerializer,ItemSerializer,SharedItemSerializer
19 from rest_framework import generics 19 from rest_framework import generics
20 - 20 +from rest_framework import status
21 +from annoying.functions import get_object_or_None
21 22
22 class UserViewSet(viewsets.ModelViewSet): 23 class UserViewSet(viewsets.ModelViewSet):
23 """ 24 """
...@@ -27,70 +28,6 @@ class UserViewSet(viewsets.ModelViewSet): ...@@ -27,70 +28,6 @@ class UserViewSet(viewsets.ModelViewSet):
27 serializer_class = UserSerializer 28 serializer_class = UserSerializer
28 permission_classes = [permissions.IsAuthenticated] 29 permission_classes = [permissions.IsAuthenticated]
29 30
30 -"""
31 -def item_list(request):
32 - if request.method == 'GET':
33 - items = Item.objects.all()
34 - serializer = ItemSerializer(items, many=True)
35 - return JsonResponse(serializer.data, safe=False)
36 - elif request.method == 'POST':
37 - s3 = boto3.client('s3')
38 - s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')
39 - file_name = request.GET['image_name']
40 - file_type = mimetypes.guess_type(file_name)[0]
41 - presigned_post = s3.generate_presigned_post(
42 - Bucket=s3_bucket,
43 - Key=file_name,
44 - Fields={"acl": "private", "Content-Type": file_type},
45 - Conditions=[
46 - {"acl": "public-read"},
47 - {"Content-Type": file_type}
48 - ],
49 - ExpiresIn=3600
50 - )
51 -
52 - data = {
53 - "signed_url": presigned_post,
54 - 'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
55 - }
56 - return presigned_post['url']
57 -
58 -def item_detail(request, pk):
59 - try:
60 - item = Item.objects.get(pk=pk)
61 - except Item.DoesNotExist:
62 - return HttpResponse(status=404)
63 -
64 - if request.method == 'GET':
65 - serializer = ItemSerializer(item)
66 - return JsonResponse(serializer.data)
67 -
68 - elif request.method == 'PUT':
69 - s3 = boto3.client('s3')
70 - s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')
71 - file_name = item.GET['image_name']
72 - file_type = mimetypes.guess_type(file_name)[0]
73 - presigned_post = s3.generate_presigned_post(
74 - Bucket=s3_bucket,
75 - Key=file_name,
76 - Fields={"acl": "private", "Content-Type": file_type},
77 - Conditions=[
78 - {"acl": "public-read"},
79 - {"Content-Type": file_type}
80 - ],
81 - ExpiresIn=3600
82 - )
83 - data = {
84 - "signed_url": presigned_post,
85 - 'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
86 - }
87 - return presigned_post['url']
88 -
89 - elif request.method == 'DELETE':
90 - item.delete()
91 - return HttpResponse(status=204)
92 -"""
93 -
94 31
95 class ItemViewSet(viewsets.ModelViewSet): 32 class ItemViewSet(viewsets.ModelViewSet):
96 33
...@@ -100,148 +37,43 @@ class ItemViewSet(viewsets.ModelViewSet): ...@@ -100,148 +37,43 @@ class ItemViewSet(viewsets.ModelViewSet):
100 #IsOwnerOrReadOnly 37 #IsOwnerOrReadOnly
101 ] 38 ]
102 39
103 - # url: /upload 40 + # url: items/search
104 - @action(methods=['POST'], detail=True, permission_classes=[AllowAny], 41 + @action(methods=['GET'], detail=False, permission_classes=[AllowAny], url_path='search', url_name='search')
105 - url_path='upload', url_name='upload') 42 + def search(self, request):
106 - def upload(self, request, pk):
107 - if request.method == 'POST':
108 - s3 = boto3.client('s3')
109 - #s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')
110 - s3_bucket = 'arn:aws:s3:::[s3id]'
111 - #file_name = request.GET['image_name']
112 - file_name = request.GET.get('image_name', '')
113 - file_type = mimetypes.guess_type(file_name)[0]
114 - presigned_post = s3.generate_presigned_post(
115 - Bucket=s3_bucket,
116 - Key=file_name,
117 - Fields={"acl": "private", "Content-Type": file_type},
118 - Conditions=[
119 - {"acl": "public-read"},
120 - {"Content-Type": file_type}
121 - ],
122 - ExpiresIn=3600
123 - )
124 -
125 - data = {
126 - "signed_url": presigned_post,
127 - 'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
128 - }
129 - return presigned_post['url']
130 -
131 - # url: /status
132 - @action(methods=['POST'], detail=True, permission_classes=[AllowAny],
133 - url_path='status', url_name='status')
134 - def status(self, request):
135 - if request.method == 'POST':
136 - #name = request.POST['name']
137 - name = request.POST.get('name', '')
138 - up_time = request.POST.get('updated_time', '')
139 - try:
140 - item = Item.objects.get(name=name, updated_time=up_time)
141 - except Item.DoesNotExist:
142 - return Response({'Error': 'File Upload Error'}, status=status.HTTP_200_OK)
143 - return Response({'Message': 'File Upload Successful'}, status=status.HTTP_200_OK)
144 -
145 - """
146 - # url: /children
147 - @action(methods=['POST'], detail=True, permission_classes=[AllowAny],
148 - url_path='children', url_name='children')
149 - def children(self, request):
150 - if request.method == 'POST':
151 - #name = request.POST['name']
152 - name = request.POST.get('name', '')
153 - path = request.POST.get('path', '')
154 - parent = request.POST.get('item_id', '')
155 - daughter = Item(name = name, path = path, parent = parent)
156 -
157 - daughter.save()
158 - """
159 -
160 -
161 -"""
162 -class ItemViewSet(viewsets.ModelViewSet):
163 -
164 - #API endpoint that allows groups to be viewed or edited.
165 -
166 - queryset = Item.objects.all().order_by('-item_id')
167 - serializer_class = ItemSerializer
168 - permission_classes = [permissions.IsAuthenticated]
169 -
170 - def item_list(self, request):
171 if request.method == 'GET': 43 if request.method == 'GET':
172 - items = Item.objects.all() 44 + keyword = request.GET.get('keyword', '')
173 - serializer = ItemSerializer(items, many=True) 45 + item_list = Item.objects.filter(name__icontains = keyword)
174 - return JsonResponse(serializer.data, safe=False)
175 - elif request.method == 'POST':
176 - s3 = boto3.client('s3')
177 - s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')
178 - file_name = request.GET['image_name']
179 - file_type = mimetypes.guess_type(file_name)[0]
180 - presigned_post = s3.generate_presigned_post(
181 - Bucket=s3_bucket,
182 - Key=file_name,
183 - Fields={"acl": "private", "Content-Type": file_type},
184 - Conditions=[
185 - {"acl": "public-read"},
186 - {"Content-Type": file_type}
187 - ],
188 - ExpiresIn=3600
189 - )
190 -
191 - data = {
192 - "signed_url": presigned_post,
193 - 'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
194 - }
195 - return presigned_post['url']
196 -"""
197 46
47 + data = serializers.serialize("json", item_list)
48 + return Response({'data': {'list' : data}}, status=status.HTTP_200_OK)
198 49
50 +class SharedItemViewSet(viewsets.ModelViewSet):
199 51
200 -""" 52 + queryset = SharedItem.objects.all()
201 - #url: /items/{item_id}/upload 53 + serializer_class = SharedItemSerializer
202 - @action(methods=['post'], detail=True, permission_classes=[IsAuthenticated], 54 + permission_classes = [permissions.IsAuthenticatedOrReadOnly, permissions.AllowAny,
203 - url_path='upload', url_name='upload') 55 + # IsOwnerOrReadOnly
204 - def upload(self, request): 56 + ]
205 - s3 = boto3.client('s3') 57 + # url: http://localhost:8000/items/1/share/
206 - s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME') 58 + # 마지막 slash도 써주어야함
207 - file_name = request.GET['image_name'] 59 + @csrf_exempt
208 - file_type = mimetypes.guess_type(file_name)[0] 60 + @action(methods=['POST'], detail=True, permission_classes=[AllowAny], url_path='share', url_name='share')
209 - presigned_post = s3.generate_presigned_post( 61 + def share(self, request, pk):
210 - Bucket=s3_bucket,
211 - Key=file_name,
212 - Fields={"acl": "private", "Content-Type": file_type},
213 - Conditions=[
214 - {"acl": "public-read"},
215 - {"Content-Type": file_type}
216 - ],
217 - ExpiresIn=3600
218 - )
219 -
220 - data = {
221 - "signed_url": presigned_post,
222 - 'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
223 - }
224 - return presigned_post['url']
225 -
226 - def upload(self, request):
227 if request.method == 'POST': 62 if request.method == 'POST':
228 - serializer = ItemSerializer(data=request.data) 63 + password = request.POST.get('password', '')
229 - if serializer.is_valid(): 64 + expires = request.POST.get('expires', '')
230 - BUCKET_NAME = 'presigned-post-example' 65 +
231 - KEY_NAME = 'cat.jpg' 66 + sharedfile = get_object_or_None(SharedItem, item_id=pk)
232 - 67 + if sharedfile != None:
233 - s3 = boto3.client('s3') 68 + # 서버는 정상이나 이미 공유객체로 등록된 파일임
234 - 69 + return Response({'Message': 'This file is already shared'}, status=status.HTTP_200_OK)
235 - resp = s3.generate_presigned_post( 70 + sharedfile = SharedItem(item_id =pk, password=password, expires = expires)
236 - Bucket = BUCKET_NAME, 71 + sharedfile.save()
237 - Key = KEY_NAME, 72 + sharedfile = SharedItem.objects.get(item_id = pk)
238 - ) 73 +
239 - 74 + # sf = serializers.serialize("json", sharedfile)
240 - resp['fields']['file'] = '@{key}'.format(key=KEY_NAME) 75 + item = Item.objects.filter(item_id = pk)
241 - 76 + item_json = serializers.serialize("json", item)
242 - form_values = "\n".join(["-F {key}={value} \\".format(key=key, value=value) 77 +
243 - for key, value in resp['fields'].items()]) 78 + # data = serializers.serialize("json", item_list)
244 - 79 + return Response({"shared": sharedfile.created_time , 'data': item_json}, status=status.HTTP_200_OK)
245 - # authentication_classes = (authentication.SessionAuthentication,)
246 - # permission_classes = [IsAuthenticated, ]
247 -"""
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -22,12 +22,14 @@ from django.conf.urls import url ...@@ -22,12 +22,14 @@ from django.conf.urls import url
22 router = routers.DefaultRouter() 22 router = routers.DefaultRouter()
23 router.register(r'users', views.UserViewSet) 23 router.register(r'users', views.UserViewSet)
24 router.register(r'items', views.ItemViewSet) 24 router.register(r'items', views.ItemViewSet)
25 +router.register(r'items', views.SharedItemViewSet)
25 26
26 # Wire up our API using automatic URL routing. 27 # Wire up our API using automatic URL routing.
27 # Additionally, we include login URLs for the browsable API. 28 # Additionally, we include login URLs for the browsable API.
28 urlpatterns = [ 29 urlpatterns = [
29 path('admin/', admin.site.urls), 30 path('admin/', admin.site.urls),
30 path('', include(router.urls)), 31 path('', include(router.urls)),
31 - url(r'^upload/$', views.ItemViewSet.upload, name='upload'), 32 + url(r'^search/$', views.ItemViewSet.search, name='search'),
32 - url(r'^status/$', views.ItemViewSet.status, name='status'), 33 + url(r'^<int:pk>/share/$', views.SharedItemViewSet.share, name='share'),
34 +
33 ] 35 ]
......