신은섭(Shin Eun Seop)
Committed by GitHub

Merge pull request #22 from kairos03/feature/user

Feature/user
...@@ -38,7 +38,8 @@ INSTALLED_APPS = [ ...@@ -38,7 +38,8 @@ INSTALLED_APPS = [
38 'django.contrib.messages', 38 'django.contrib.messages',
39 'django.contrib.staticfiles', 39 'django.contrib.staticfiles',
40 'rest_framework', 40 'rest_framework',
41 - 'restful.apps.RestfulConfig' 41 + 'restful.apps.RestfulConfig',
42 + 'website'
42 ] 43 ]
43 44
44 MIDDLEWARE = [ 45 MIDDLEWARE = [
...@@ -105,7 +106,7 @@ AUTH_PASSWORD_VALIDATORS = [ ...@@ -105,7 +106,7 @@ AUTH_PASSWORD_VALIDATORS = [
105 # Internationalization 106 # Internationalization
106 # https://docs.djangoproject.com/en/2.0/topics/i18n/ 107 # https://docs.djangoproject.com/en/2.0/topics/i18n/
107 108
108 -LANGUAGE_CODE = 'en-us' 109 +LANGUAGE_CODE = 'ko_kr'
109 110
110 TIME_ZONE = 'UTC' 111 TIME_ZONE = 'UTC'
111 112
...@@ -120,3 +121,8 @@ USE_TZ = True ...@@ -120,3 +121,8 @@ USE_TZ = True
120 # https://docs.djangoproject.com/en/2.0/howto/static-files/ 121 # https://docs.djangoproject.com/en/2.0/howto/static-files/
121 122
122 STATIC_URL = '/static/' 123 STATIC_URL = '/static/'
124 +
125 +
126 +# Login redirect
127 +
128 +LOGIN_REDIRECT_URL = '/'
...\ No newline at end of file ...\ No newline at end of file
......
1 -"""dcloud URL Configuration
2 -
3 -The `urlpatterns` list routes URLs to views. For more information please see:
4 - https://docs.djangoproject.com/en/2.0/topics/http/urls/
5 -Examples:
6 -Function views
7 - 1. Add an import: from my_app import views
8 - 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 -Class-based views
10 - 1. Add an import: from other_app.views import Home
11 - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 -Including another URLconf
13 - 1. Import the include() function: from django.urls import include, path
14 - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 -"""
16 from django.contrib import admin 1 from django.contrib import admin
17 from django.conf.urls import url, include 2 from django.conf.urls import url, include
3 +from django.contrib.auth import views
18 4
19 urlpatterns = [ 5 urlpatterns = [
20 - url('admin/', admin.site.urls), 6 + url(r'^admin/', admin.site.urls),
21 - url(r'^', include('restful.urls')), 7 + url(r'^restapi/', include('restful.urls')),
8 + url(r'^', include('website.urls')),
9 +
10 + url(r'^accounts/login/$', views.login, name='login'),
11 + url(r'^accounts/logout/$', views.logout, name='logout', kwargs={'next_page': '/'}),
12 +
22 ] 13 ]
14 +
......
1 +#!/bin/bash
2 +rm -f db.sqlite3
3 +rm -r restful/migrations
4 +python manage.py makemigrations restful
5 +python manage.py migrate
1 from django.db import models 1 from django.db import models
2 2
3 -
4 # Create your models here. 3 # Create your models here.
5 class File(models.Model): 4 class File(models.Model):
6 created = models.DateTimeField(auto_now_add=True) 5 created = models.DateTimeField(auto_now_add=True)
7 modified = models.DateTimeField(auto_now=True) 6 modified = models.DateTimeField(auto_now=True)
8 title = models.CharField(max_length=100) 7 title = models.CharField(max_length=100)
8 + # file_name = models.CharField(max_length=100, primary_key=True)
9 +
9 object_key = models.CharField(max_length=1025) 10 object_key = models.CharField(max_length=1025)
10 - size = models.IntegerField()
11 # owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE) 11 # owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
12 12
13 class Meta: 13 class Meta:
14 - ordering = ('title',) 14 + ordering = ('pk',)
15 -
16 -
......
1 +import boto3
2 +import json
3 +
4 +S3 = boto3.client('s3')
5 +BUCKET = '2018-dcloud'
6 +
7 +
8 +def list_path(bucket, user, path):
9 +
10 + files = []
11 + # get list
12 + objects = S3.list_objects(Bucket=bucket, Prefix='{}/{}'.format(user, path), Delimiter='/')
13 +
14 + # get sub directorys
15 + common_prefixes = objects.get('CommonPrefixes')
16 + if common_prefixes:
17 + for obj in common_prefixes:
18 + files.append({'type':'diretory', 'name':obj.get('Prefix').split('/')[-2]})
19 +
20 + # get files
21 + contents = objects.get('Contents')
22 + if contents:
23 + for obj in contents:
24 + file = obj.get('Key').split('/')[-1]
25 + if file != '':
26 + files.append({'type':'file', 'name':file})
27 +
28 + return {'files':files}
29 +
30 +# print(list_path(BUCKET, 'test1', ''))
...\ No newline at end of file ...\ No newline at end of file
...@@ -3,30 +3,8 @@ from rest_framework import serializers ...@@ -3,30 +3,8 @@ from rest_framework import serializers
3 from restful.models import File 3 from restful.models import File
4 4
5 5
6 -class FileSerializer(serializers.Serializer): 6 +class FileSerializer(serializers.ModelSerializer):
7 - pk = serializers.IntegerField(read_only=True)
8 - created = serializers.DateTimeField(read_only=True)
9 - modified = serializers.DateTimeField(read_only=True)
10 - title = serializers.CharField(max_length=100)
11 - object_key = serializers.CharField(max_length=1025)
12 - size = serializers.IntegerField()
13 7
14 - 8 + class Meta:
15 - def create(self, validated_data): 9 + model = File
16 - """ 10 + fields = ('created', 'updated', 'object_key')
17 - Create and Return new `File` instance. Using validated_data.
18 - """
19 - return File.objects.create(**validated_data)
20 -
21 -
22 - def update(self, instance, validated_data):
23 - """
24 - Update and Return existing `File` instance. Using validated_data.
25 - """
26 - instance.title = validated_data.get('title', instance.title)
27 - instance.object_key = validated_data.get('object_key', instance.object_key)
28 - instance.size = validated_data.get('size', instance.size)
29 - instance.language = validated_data.get('language', instance.language)
30 - instance.style = validated_data.get('style', instance.style)
31 - instance.save()
32 - return instance
......
1 -from django.test import TestCase 1 +from rest_framework.test import APITestCase
2 +from django.urls import reverse
3 +from rest_framework import status
4 +from restful.models import File
5 +
6 +
7 +class FileListTestCase(APITestCase):
8 +
9 + def setUp(self):
10 + self.tearDown()
11 +
12 + def tearDown(self):
13 + pass
14 +
15 + def test_upload(self):
16 + url = reverse('file-list')
17 + data = {'object_key': 'test_object_key'}
18 + response = self.client.post(url, data)
19 + self.assertEqual(response.status_code, status.HTTP_201_CREATED)
20 + self.assertEqual(File.objects.count(), 1)
21 +
22 + def test_list(self):
23 + url = reverse('file-list')
24 + response = self.client.get(url)
25 + self.assertEqual(response.status_code, status.HTTP_200_OK)
26 +
27 +
28 +class FileDetailTestCase(APITestCase):
29 +
30 + def setUp(self):
31 + self.tearDown()
32 + File.objects.create(object_key='test_object')
33 +
34 + def tearDown(self):
35 + File.objects.all().delete()
36 +
37 + def test_delete(self):
38 + url = reverse('file-detail', kwargs={'pk' : 1 })
39 + response = self.client.delete(url)
40 + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
41 +
42 + def test_update(self):
43 + url = reverse('file-detail', kwargs={'pk' : 1 })
44 + response = self.client.put(url, {"object_key":"test_update"})
45 + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
46 +
47 + def test_retrieve(self):
48 + url = reverse('file-detail', kwargs={'pk' : 1 })
49 + response = self.client.get(url)
50 + self.assertEqual(response.status_code, status.HTTP_200_OK)
51 +
52 +
2 53
...\ No newline at end of file ...\ No newline at end of file
3 -# Create your tests here.
......
1 from django.conf.urls import url 1 from django.conf.urls import url
2 +from django.shortcuts import redirect
2 from rest_framework.urlpatterns import format_suffix_patterns 3 from rest_framework.urlpatterns import format_suffix_patterns
3 from restful import views 4 from restful import views
4 5
5 urlpatterns = [ 6 urlpatterns = [
6 - url(r'^files/$', views.FileList.as_view()), 7 + url(r'^files/(?P<path>([a-zA-z0-9가-힣._-]*/)*)$', views.FileList.as_view(), name='file-list'),
7 url(r'^files/(?P<pk>[0-9]+)/$', views.FileDetail.as_view()), 8 url(r'^files/(?P<pk>[0-9]+)/$', views.FileDetail.as_view()),
8 ] 9 ]
9 10
......
1 -from restful.models import File
2 -from restful.serializers import FileSerializer
3 from django.http import Http404 1 from django.http import Http404
2 +from django.contrib.auth.decorators import login_required
4 from rest_framework.views import APIView 3 from rest_framework.views import APIView
5 from rest_framework.response import Response 4 from rest_framework.response import Response
6 from rest_framework import status 5 from rest_framework import status
6 +from restful import s3_interface
7 7
8 +from restful.models import File
9 +from restful.serializers import FileSerializer
8 10
9 -# Create your views here.
10 class FileList(APIView): 11 class FileList(APIView):
11 """ 12 """
12 List all file, or create a new snippet. 13 List all file, or create a new snippet.
13 """ 14 """
14 15
15 - def get(self, request, format=None): 16 + def get(self, request, path='/', format=None):
16 - file = File.objects.all() 17 + # file = File.objects.all()
17 - serializer = FileSerializer(file, many=True) 18 + # serializer = FileSerializer(file, many=True)
18 - return Response(serializer.data) 19 + # print(serializer.data)
20 + # return Response(serializer.data)
21 + data = s3_interface.list_path(s3_interface.BUCKET, 'test1', path)
22 + return Response(data)
23 +
19 24
20 def post(self, request, format=None): 25 def post(self, request, format=None):
21 serializer = FileSerializer(data=request.data) 26 serializer = FileSerializer(data=request.data)
...@@ -38,14 +43,14 @@ class FileDetail(APIView): ...@@ -38,14 +43,14 @@ class FileDetail(APIView):
38 def get(self, request, pk, format=None): 43 def get(self, request, pk, format=None):
39 file = self.get_object(pk) 44 file = self.get_object(pk)
40 serializer = FileSerializer(file) 45 serializer = FileSerializer(file)
41 - return Response(serializer.data) 46 + return Response(serializer.data, status=status.HTTP_200_OK)
42 47
43 def put(self, request, pk, format=None): 48 def put(self, request, pk, format=None):
44 file = self.get_object(pk) 49 file = self.get_object(pk)
45 serializer = FileSerializer(file, data=request.data) 50 serializer = FileSerializer(file, data=request.data)
46 if serializer.is_valid(): 51 if serializer.is_valid():
47 serializer.save() 52 serializer.save()
48 - return Response(serializer.data) 53 + return Response(serializer.data, status=status.HTTP_204_NO_CONTENT)
49 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 54 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
50 55
51 def delete(self, request, pk, format=None): 56 def delete(self, request, pk, format=None):
......
1 +from django.contrib import admin
2 +# from website.models import Post
3 +
4 +# admin.site.register(Post)
...\ No newline at end of file ...\ No newline at end of file
1 +from django.apps import AppConfig
2 +
3 +
4 +class WebsiteConfig(AppConfig):
5 + name = 'website'
1 +from django.contrib.auth import login, authenticate, logout
2 +from django.contrib.auth.forms import UserCreationForm
3 +from django.shortcuts import render, redirect
4 +from django.contrib.auth.decorators import login_required
5 +
6 +def signup(request):
7 + if request.method == 'POST':
8 + form = UserCreationForm(request.POST)
9 + if form.is_valid():
10 + form.save()
11 + username = form.cleaned_data.get('username')
12 + raw_password = form.cleaned_data.get('password1')
13 + user = authenticate(username=username, password=raw_password)
14 + login(request, user)
15 + return redirect('/')
16 + else:
17 + form = UserCreationForm()
18 + return render(request, 'registration/signup.html', {'form': form})
19 +
20 +
21 +@login_required
22 +def delete_account(request):
23 + if request.method == 'GET':
24 + return render(request, 'registration/delete_account.html')
25 + elif request.method == 'POST':
26 + if request.POST.get('yes'):
27 + return redirect('delete_account_success')
28 + else:
29 + return redirect('/')
30 +
31 +@login_required
32 +def delete_account_success(request):
33 + if request.method == 'GET':
34 + # TODO Add delete account
35 + logout(request)
36 + return render(request, 'registration/delete_account_success.html')
37 +
1 +from django import forms
2 +
3 +# class PostForm(forms.ModelForm):
4 +# class Meta:
5 +# model = Post
6 +# fields = ('title', 'text')
...\ No newline at end of file ...\ No newline at end of file
1 +from django.db import models
2 +from django.utils import timezone
3 +
1 +h1 a {
2 + color: #FCA205;
3 + font-family: 'Lobster';
4 +}
5 +
6 +body {
7 + padding-left: 15px;
8 +}
9 +
10 +.page-header {
11 + background-color: #ff9400;
12 + margin-top: 0;
13 + padding: 20px 20px 20px 40px;
14 +}
15 +
16 +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
17 + color: #ffffff;
18 + font-size: 36pt;
19 + text-decoration: none;
20 +}
21 +
22 +.content {
23 + margin-left: 40px;
24 +}
25 +
26 +h1, h2, h3, h4 {
27 + font-family: 'Lobster', cursive;
28 +}
29 +
30 +.date {
31 + color: #828282;
32 +}
33 +
34 +.save {
35 + float: right;
36 +}
37 +
38 +.post-form textarea, .post-form input {
39 + width: 100%;
40 +}
41 +
42 +.top-menu, .top-menu:hover, .top-menu:visited {
43 + color: #ffffff;
44 + float: right;
45 + font-size: 26pt;
46 + margin-right: 20px;
47 +}
48 +
49 +.post {
50 + margin-bottom: 70px;
51 +}
52 +
53 +.post h1 a, .post h1 a:visited {
54 + color: #000000;
55 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends "website/baseline.html" %}
2 +
3 +{% block content %}
4 +{% if user.is_authenticated %}
5 +<h1> {{user.username}} really want to delete your account? </h1>
6 +<form action='#' method="POST">
7 + {% csrf_token %}
8 + <input type="submit" value="yes" name="yes">
9 + <input type="submit" value="no" name="no">
10 +</form>
11 +{% endif %}
12 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends "website/baseline.html" %}
2 +
3 +{% block content %}
4 +<h1>DELTED</h1>
5 +<!--TODO AUTO logout -->
6 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends "website/baseline.html" %}
2 +
3 +{% block content %}
4 + {% if form.errors %}
5 + <p>이름과 비밀번호가 일치하지 않습니다. 다시 시도해주세요.</p>
6 + {% endif %}
7 +
8 + <form method="post" action="{% url 'login' %}">
9 + {% csrf_token %}
10 + <table>
11 + <tr>
12 + <td>{{ form.username.label_tag }}</td>
13 + <td>{{ form.username }}</td>
14 + </tr>
15 + <tr>
16 + <td>{{ form.password.label_tag }}</td>
17 + <td>{{ form.password }}</td>
18 + </tr>
19 + </table>
20 +
21 + <input type="submit" value="login" />
22 + <input type="hidden" name="next" value="{{ next }}" />
23 + </form>
24 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends 'website/baseline.html' %} {% block content %}
2 +<h2>Sign up</h2>
3 +<form method="post">
4 + {% csrf_token %} {% for field in form %}
5 + <p>
6 + {{ field.label_tag }}
7 + <br> {{ field }} {% if field.help_text %}
8 + <small style="color: grey">{% autoescape off %}{{ field.help_text }}{% endautoescape %}</small>
9 + {% endif %} {% for error in field.errors %}
10 + <p style="color: red">{{ error }}</p>
11 + {% endfor %}
12 + </p>
13 + {% endfor %}
14 + <button type="submit">Sign up</button>
15 +</form>
16 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +<html>
2 + <header>
3 + <title>D.cloud</title>
4 + </header>
5 + <body>
6 + <div class="page-header">
7 + {% if user.is_authenticated %}
8 + <p class="top-menu">Hello {{ user.username }} <small>(<a href="{% url 'logout' %}">Log out</a>)</small></p>
9 + {% else %}
10 + <a href="{% url 'login' %}" class="top-menu">Log in<span class="glyphicon glyphicon-lock"></span></a>
11 + {% endif %}
12 + <h1><a href="/">D.cloud</a></h1>
13 + </div>
14 + <div class="content">
15 + {% block content %}
16 + {% endblock %}
17 + </div>
18 + <div class="page-footer">
19 +
20 + </div>
21 + </body>
22 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends 'website/baseline.html' %}
2 +
3 +{% block content %}
4 + {% for file in files %}
5 + <h1>{{file.name}}</h1>
6 + <p>{{file.type}}</p>
7 + {% endfor %}
8 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +{% extends 'website/baseline.html' %}
2 +
3 +{% block content %}
4 + <h1> Hello </h1>
5 +{% endblock %}
...\ No newline at end of file ...\ No newline at end of file
1 +from django.test import TestCase
2 +
3 +# Create your tests here.
1 +from django.conf.urls import url
2 +from django.shortcuts import redirect
3 +from website import views, auth_views
4 +
5 +urlpatterns = [
6 +
7 + url(r'^accounts/signup/$', auth_views.signup, name='signup'),
8 + url(r'^accounts/delete_account/$', auth_views.delete_account, name='delete_account'),
9 + url(r'^accounts/delete_account_success/$', auth_views.delete_account_success, name='delete_account_success'),
10 +
11 + # blog
12 + url(r'^$', views.home),
13 + url(r'^files/', views.file_list, name='file_list'),
14 +]
...\ No newline at end of file ...\ No newline at end of file
1 +from django.shortcuts import render, get_object_or_404, redirect, Http404
2 +from django.utils import timezone
3 +from django.contrib.auth.decorators import login_required
4 +from restful.models import File
5 +import requests
6 +
7 +
8 +def home(request):
9 + return render(request, 'website/home.html')
10 +
11 +
12 +@login_required
13 +def file_list(request):
14 + files = requests.get('http://localhost:8000/restapi/files')
15 + files = files.json()
16 + return render(request, 'website/file_list.html', files)