⛳
Django Rest Framework チュートリアル
やること
Django Rest Framework(今後DRFと呼称)でapiを作成し、user情報を確認する。
- 下記の内容に沿ってチュートリアルをこなす。
https://www.django-rest-framework.org/tutorial/quickstart/
環境
- python version 3.9.17
- Django version 4.2.3
- Django Rest Framework version 3.14.0
- Docker上での開発
ディレクトリ構造
/drfTest
├── drfTest/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
├── manage.py
前準備
DRFを導入し、accountsというアプリを作成しておく。
するとディレクトリ構造としてはこうなる
ディレクト構造
./drfTest/
├── accounts/
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py
├── drfTest/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
├── db.sqlite3
├── manage.py
ユーザーモデルの作成
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError("The Email field must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
password = models.CharField(max_length=128)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['password']
def __str__(self):
return self.email
上記コードを入力したらターミナルで
terminal
python manage.py makemigrations
python manage.py migrate
上記コマンドを入力し、マイグレーションする。
ユーザ作成
ターミナルでユーザーを作成する。
terminal
python manage.py createsuperuser --email admin@example.com --password 1234
このコマンドで下記のユーザができる
- メールアドレス : admin@example.com
- パスワード : 1234
シリアライザーとViewSetの作成
accountsフォルダ内にserializers.pyを作成する。
その後、下記のコードを入力する。
accounts/serializers.py
from rest_framework import serializers
from .models import CustomUser
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ['id', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = CustomUser(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
serializers.pyの補足
-
extra_kwargs
で何をしているか?-
password
フィールドをwrite_only
にすることで、クライアントはpassword
の情報を書き込むことはできるが、読み取りができなくなる。
-
- 'create'メソッドとは?
- API経由で新しいデータを作成するメソッド。DRF側で作成されているため、別の名前では機能しない
accounts/views.py
from django.shortcuts import render
from .models import CustomUser
from rest_framework import viewsets
from rest_framework import permissions
from .serializers import CustomUserSerializer
class CustomUserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
permission_classes = [permissions.IsAuthenticated]
views.pyの補足
-
permission_classes
とはなにか?- このデータにアクセスできる権限の設定。
ルーティングの設定
下記コードを記述
drfTest/urls.py
from django.urls import include, path
from rest_framework import routers
from accounts import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
ページネーションの設定
drfTest/settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
また、settings.pyにrest-frameworkを追加する
drfTest/settings.py
INSTALLED_APPS = [
...
+ 'rest_framework',
]
テストしてみる
terminal
python manage.py runserver 8001
上記コマンドでDjangoサーバーを起動して、
http://localhost:8001/users にアクセスすると作成したすべてのユーザーをGETすることができる。
また、http://localhost:8001/users/1 にアクセスするとことで id = 1
のユーザのみを取得することが可能である。
改善するとしたら?
- usersでアクセスしたらすべてのユーザーが表示されてしまうので、それができないようにする。
- idをUUIDにすることで推測をできなくさせ、自身の情報だけを見られるようにする。
参考
最初に書いたものと同じだが改めて記す。
Discussion