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 |