forked from CEOS-Developers/django-vote-14th
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [test]: 컨테이너간 포트포워딩 테스트 * [test]: 컨테이너 포트포워딩 테스트2 * Create User, Candidate models * Create serializer * Create Views * merge * [etc]: branch merge * [test]: 자동배포 에러 해결을 위한 테스트 코드 추가 * [test]: 자동배포 에러 해결을 위한 테스트 코드 추가 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [etc]: migration 내용 추가 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [fix]: 오타 수정 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [test]:자동배포 에러 해결을 위한 테스트 코드 추가 * [test]: migrations 파일 추가 * [test]: prod.py setting pymysql 추가 * [feat]: CORS 셋팅 * [etc]: migrate 파일 추가 Co-authored-by: YOONJI KIM <[email protected]>
- Loading branch information
1 parent
1dd88b0
commit 1a55c2c
Showing
13 changed files
with
375 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Generated by Django 3.0.8 on 2021-12-02 11:17 | ||
|
||
import api.models | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='Candidate', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('created_date', models.DateTimeField(auto_now_add=True)), | ||
('updated_date', models.DateTimeField(auto_now=True)), | ||
('name', models.CharField(max_length=50)), | ||
('votes', models.IntegerField(default=0)), | ||
], | ||
options={ | ||
'abstract': False, | ||
}, | ||
), | ||
migrations.CreateModel( | ||
name='User', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('password', models.CharField(max_length=128, verbose_name='password')), | ||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), | ||
('created_date', models.DateTimeField(auto_now_add=True)), | ||
('updated_date', models.DateTimeField(auto_now=True)), | ||
('email', models.EmailField(max_length=255, unique=True, verbose_name='email')), | ||
('userid', models.CharField(max_length=50, unique=True)), | ||
('voteDone', models.BooleanField(default=False)), | ||
('voting_for', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='voters', to='api.Candidate')), | ||
], | ||
options={ | ||
'abstract': False, | ||
}, | ||
managers=[ | ||
('objects', api.models.UserManager()), | ||
], | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,68 @@ | ||
from django.db import models | ||
from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser) | ||
|
||
# Create your models here. | ||
|
||
|
||
class Base(models.Model): | ||
created_date = models.DateTimeField(auto_now_add=True) | ||
updated_date = models.DateTimeField(auto_now=True) | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
|
||
class Candidate(Base): | ||
name = models.CharField(max_length=50, null=False) | ||
votes = models.IntegerField(default=0) | ||
|
||
|
||
class UserManager(BaseUserManager): | ||
use_in_migrations = True | ||
|
||
def create_user(self, email, userid, password=None): | ||
if not "email": | ||
raise ValueError('Users must have an email address') | ||
|
||
user = self.model( | ||
email=self.normalize_email(email), | ||
userid=userid, | ||
) | ||
user.set_password(password) | ||
user.save(using=self._db) | ||
return user | ||
|
||
def create_superuser(self, email, userid, password): | ||
superuser = self.create_user( | ||
email=self.normalize_email(email), | ||
userid=userid, | ||
password=password) | ||
superuser.is_admin = True | ||
superuser.is_superuser = True | ||
superuser.save(using=self._db) | ||
return superuser | ||
|
||
|
||
class User(AbstractBaseUser, Base): | ||
email = models.EmailField( | ||
verbose_name='email', | ||
max_length=255, | ||
unique=True, | ||
) | ||
userid = models.CharField(max_length=50, unique=True, null=False) | ||
voteDone = models.BooleanField(default=False) | ||
voting_for = models.ForeignKey(Candidate, on_delete=models.CASCADE, related_name='voters', null=True) | ||
|
||
objects = UserManager() | ||
|
||
USERNAME_FIELD = 'email' | ||
REQUIRED_FIELDS = [] | ||
|
||
def __str__(self): | ||
return self.email | ||
|
||
def has_perm(self, perm, obj=None): | ||
return True | ||
|
||
def has_module_perms(self, app_label): | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from rest_framework import serializers | ||
from rest_framework_jwt.settings import api_settings | ||
from django.contrib.auth.backends import ModelBackend | ||
from django.contrib.auth import authenticate | ||
from django.contrib.auth.models import update_last_login | ||
from django.contrib.auth import get_user_model | ||
from .models import * | ||
|
||
# JWT 사용을 위한 설정 | ||
JWT_PAYLOAD_HANDLER = api_settings.JWT_PAYLOAD_HANDLER | ||
JWT_ENCODE_HANDLER = api_settings.JWT_ENCODE_HANDLER | ||
|
||
User = get_user_model() | ||
|
||
# 회원가입. | ||
class UserSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = User | ||
fields = ['userid', 'email', 'password'] | ||
|
||
def create(self, validated_data): | ||
user = User.objects.create( | ||
email=validated_data['email'], | ||
userid=validated_data['userid'], | ||
password=validated_data['password'], | ||
) | ||
#user.set_password(validated_data['password']) | ||
user.save() | ||
return user | ||
|
||
|
||
class LoginBackend(ModelBackend): # 준환님 readme.md 참고. 이거 안하면 계속 userid=None 나옴.. | ||
def authenticate(self, request, userid=None, password=None, **kwargs): | ||
try: | ||
user = User.objects.get(userid=userid) | ||
#if user.check_password(password): | ||
if user.password == password: | ||
return user | ||
return None | ||
|
||
except User.DoesNotExist: | ||
return None | ||
|
||
|
||
# 로그인 | ||
class UserLoginSerializer(serializers.ModelSerializer): | ||
userid = serializers.CharField(max_length=50) | ||
password = serializers.CharField(max_length=150, write_only=True) | ||
token = serializers.CharField(max_length=255, read_only=True) | ||
|
||
class Meta: | ||
model = User | ||
fields = ['userid', 'password', 'token'] | ||
|
||
def validate(self, data): | ||
userid = data.get("userid", None) | ||
password = data.get("password", None) | ||
user = authenticate(userid=userid, password=password) | ||
|
||
if user is None: | ||
return {'userid': 'None'} # password가 안맞아도 해당 에러. | ||
try: | ||
payload = JWT_PAYLOAD_HANDLER(user) | ||
jwt_token = JWT_ENCODE_HANDLER(payload) | ||
update_last_login(None, user) | ||
|
||
except User.DoesNotExist: | ||
raise serializers.ValidationError( | ||
'User does not exist' | ||
) | ||
return { | ||
'userid': user.userid, | ||
'token': jwt_token | ||
} | ||
|
||
|
||
class CandidateSerializer(serializers.ModelSerializer): | ||
voters = UserSerializer(many=True, read_only=True) | ||
class Meta: | ||
model = Candidate | ||
fields = ['name', 'votes', 'voters'] | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from django.urls import path, include | ||
from . import views | ||
from .views import * | ||
from rest_framework import routers | ||
from rest_framework_jwt.views import verify_jwt_token | ||
from rest_framework_jwt.views import obtain_jwt_token | ||
from rest_framework_jwt.views import refresh_jwt_token | ||
|
||
router = routers.DefaultRouter() | ||
router.register(r'users', UserViewSet) | ||
router.register(r'candidates', CandidateViewSet) | ||
|
||
urlpatterns = router.urls | ||
|
||
urlpatterns += [ | ||
path('users/login', views.LoginView.as_view()), | ||
path('users/vote/<int:id>', views.VoteView.as_view()), | ||
path('token', obtain_jwt_token), | ||
path('users/token/refresh', refresh_jwt_token), | ||
path('users/token/verify', verify_jwt_token), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,64 @@ | ||
from .models import User, Candidate | ||
from .serializers import * | ||
from rest_framework.views import APIView | ||
from rest_framework import viewsets | ||
from rest_framework.permissions import IsAuthenticated, AllowAny | ||
from rest_framework.response import Response | ||
from rest_framework import status | ||
from rest_framework.generics import get_object_or_404 | ||
from rest_framework.filters import OrderingFilter | ||
|
||
# Create your views here. | ||
|
||
User = get_user_model() | ||
|
||
|
||
class UserViewSet(viewsets.ModelViewSet): | ||
permission_classes = (AllowAny,) | ||
queryset = User.objects.all() | ||
serializer_class = UserSerializer | ||
|
||
|
||
class CandidateViewSet(viewsets.ModelViewSet): | ||
permission_classes = (AllowAny,) | ||
queryset = Candidate.objects.all() | ||
serializer_class = CandidateSerializer | ||
filter_backends = [OrderingFilter] | ||
# ordering_fields = ['-votes'] # 정렬 허용 리스트 | ||
ordering = ['-votes'] # default 정렬 지정 | ||
|
||
|
||
class LoginView(APIView): | ||
permission_classes = (AllowAny,) | ||
|
||
def post(self, request, format=None): | ||
serializer = UserLoginSerializer(data=request.data) | ||
if serializer.is_valid(): | ||
return Response(serializer.data, status=status.HTTP_201_CREATED) | ||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
|
||
class VoteView(APIView): | ||
permission_classes = (IsAuthenticated,) | ||
|
||
def get_object(self, id): | ||
candidate = get_object_or_404(Candidate, pk=id) | ||
return candidate | ||
|
||
def get(self, request, id, format=None): | ||
candidate = self.get_object(id) | ||
user = request.user | ||
if user.voteDone: | ||
return Response({"message":"voteDone"}, status=status.HTTP_403_FORBIDDEN) | ||
|
||
user.voting_for = candidate | ||
user.voteDone = True | ||
candidate.votes += 1 | ||
user.save() | ||
candidate.save() | ||
return Response({"message":"Successfully Voted to " + user.voting_for.name}, status=status.HTTP_200_OK) | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.