ssung_데이터 엔지니어링/3주차_장고 활용한 API 서버 만들기

Django 활용하기(4)

ssungcohol 2023. 11. 2. 15:49

User 추가하기

# polls/models.py

class Question(models.Model):
    question_text = models.CharField(max_length=200, verbose_name='질문')
    pub_date = models.DateTimeField(auto_now_add=True, verbose_name='생성일')
    
    # admin이 아닌 일반 user 추가
    owner = models.ForeignKey('auth.User', related_name='questions', on_delete=models.CASCADE, null=True)
                              
    @admin.display(boolean=True, description='최근생성(하루기준)')
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    
    def __str__(self):
        return f'제목: {self.question_text}, 날짜: {self.pub_date}'

User 관리하기

  • pk를 통해 여러개의 question을 가질 수 있다
# polls_api/serializers.py - user serializer 생성

from django.contrib.auth.models import User

class UserSerializer(serializers.ModelSerializer):
    questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())
    
    class Meta:
        model = User
        fields = ['id', 'username', 'questions']
  • view.py 구현과 그에 맞는 urls.py 구현
# polls_api/views.py

from django.contrib.auth.models import User
from polls_api.serializers import UserSerializer

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
#==============================================

# polls_api/urls.py

from django.urls import path
from .views import *

urlpatterns = [
    path('question/', QuestionList.as_view(), name='question-list'),
    path('question/<int:pk>/', QuestionDetail.as_view()),
    path('users/', UserList.as_view(),name='user-list'),
    path('users/<int:pk>/', UserDetail.as_view()),
]

Form을 사용해 User 생성하기

  • 장고에서 제공하는 기능을 사용하여 생성
  • Generic View - 장고에서 기본적으로 제공하는 뷰의 형태, 개발 속도를 더욱 빠르게 만들어 줌
  • reverse_lazy() - url에서 정의했던 path에서 이름(name)을 기반으로 url을 생성 가능
  • UserCreationForm - '유저이름'과 '패스워드', '패스워드 확인' 필드를 제공, 회원가입 폼을 자동 생성
# polls/views.py

from django.views import generic
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm

class SignupView(generic.CreateView):
    form_class = UserCreationForm
    success_url = reverse_lazy('user-list')
    template_name = 'registration/signup.html'
    
# ===============================================

# polls/templates/registration/signup.html

<h2>회원가입</h2>
 <form method="post">
   {% csrf_token %}
   {{ form.as_p }}
   <button type="submit">가입하기</button>
</form>

# {{ form.as_p }} = UserCreationForm을 렌더링한 결과 출력
# ================================================

# polls/urls.py

from django.urls import path
from . import views
from .views import *

app_name = 'polls'
urlpatterns = [
    path('',views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/vote/', views.vote, name='vote'), 
    path('<int:question_id>/result/', views.result, name='result'), 
    path('signup/', SignupView.as_view(), )
]

Serializer를 사용해 User 생성하기

  • from django.contrib.auth.password_validation import validate_password
     - 단순한 비밀번호 입력 방지

 

# polls_api/serializers.py

from django.contrib.auth.password_validation import validate_password

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
    password2 = serializers.CharField(write_only=True, required=True)
    
    # password가 일치하는지 확인하는 method 작성
    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError({"password": "두 패스워드가 일치하지 않습니다."})
        return attrs
    
    def create(self, validated_data):
        user = User.objects.create(username=validated_data['username'])
        user.set_password(validated_data['password'])
        user.save()
        
        return user
    
    class Meta:
        model = User
        fields = ['username', 'password','password2']
        
# ===========================================================

# polls_api/views.py

from polls_api.serializers import RegisterSerializer

class RegisterUser(generics.CreateAPIView):
    serializer_class = RegisterSerializer
    
# ============================================================

# polls_api/urls.py

from django.urls import path
from .views import *

urlpatterns = [
    path('question/', QuestionList.as_view(), name='question-list'),
    path('question/<int:pk>/', QuestionDetail.as_view()),
    path('users/', UserList.as_view(),name='user-list'),
    path('users/<int:pk>/', UserDetail.as_view()),
    path('register/', RegisterUser.as_view()),
]

User 권한 관리

# polls_api/urls.py

from django.urls import path,include
from .views import *

urlpatterns = [
    path('question/', QuestionList.as_view(), name='question-list'),
    path('question/<int:pk>/', QuestionDetail.as_view()),
    path('users/', UserList.as_view(),name='user-list'),
    path('users/<int:pk>/', UserDetail.as_view()),
    path('register/', RegisterUser.as_view()),
    path('api-auth/', include('rest_framework.urls'))
]

# ==========================================

# mysite/settings.py

from django.urls import reverse_lazy
LOGIN_REDIRECT_URL = reverse_lazy('question-list')
LOGOUT_REDIRECT_URL = reverse_lazy('question-list')

# ==========================================

# polls_api/serializers.py

class QuestionSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')

    class Meta:
        model = Question
        fields = ['id', 'question_text', 'pub_date', 'owner']
        
# ==========================================

# polls_api/permissions.py

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        
        return obj.owner == request.user
        
# ==========================================

# polls_api/views.py

from rest_framework import generics,permissions
from .permissions import IsOwnerOrReadOnly

class QuestionList(generics.ListCreateAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
728x90

'ssung_데이터 엔지니어링 > 3주차_장고 활용한 API 서버 만들기' 카테고리의 다른 글

Django 활용하기(5)  (1) 2023.11.03
Django 활용하기(3)  (0) 2023.11.01
Django 활용하기(2)  (0) 2023.10.31
Django 활용하기(1)  (0) 2023.10.30