目的
- とにかくやりきることが一番の目的
- 毎日発信することで、発信する習慣作り
- 個人開発をやりきることで、実績作り
開発するもの
X(旧Twitter)のパクリ
構成
- バックエンド
- python
- django REST framework
- DB
- postgreSQL
- フロントエンド
- React
本編
前回会員登録画面の表示ができたので、会員登録APIの作成とreactから会員登録APIを実行するところを作成する。
djangoで会員登録APIの作成をする
user
アプリを作成する
この記事でtweet
アプリは作成した。
それとは別にuser
を作成することで、機能を分ける。
django-admin startapp user
設定を追加
INSTALLED_APPS = [
'likeX.user.apps.UserConfig',
]
Userモデルの作成
tweet
のmodels.pyから移設。
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.CharField(max_length=280, blank=True)
location = models.CharField(max_length=100, blank=True)
birth_date = models.DateField(null=True, blank=True)
# groups と user_permissions の related_name を変更する
groups = models.ManyToManyField(
'auth.Group',
verbose_name='groups',
blank=True,
help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
related_name='tweet_user_set', # ここを変更
related_query_name='user',
)
user_permissions = models.ManyToManyField(
'auth.Permission',
verbose_name='user permissions',
blank=True,
help_text='Specific permissions for this user.',
related_name='tweet_user_set', # ここを変更
related_query_name='user_permission',
)
デフォルト設定だと、django.contrib.auth
が適用されていて、認証userとしてUser
が適用されないため、以下の設定を追加。
AUTH_USER_MODEL = 'user.User'
すでに作成済みのテーブルをすべて削除し、マイグレーションを実行。
こうすることで、作成済みのdjango.contrib.auth
のテーブルが削除され、User
のテーブルが認証系のテーブルとして適用される。
python manage.py migrate
serializer,viewの作成
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
class Meta:
model = User
fields = ('username', 'email', 'password')
def create(self, validated_data):
# パスワードを validated_data から削除し、ユーザー作成後に設定する
password = validated_data.pop('password', None)
user = User.objects.create_user(**validated_data)
if password is not None:
user.set_password(password)
user.save()
return user
from django.db import transaction
from rest_framework import permissions, generics
from rest_framework.response import Response
from rest_framework import status
from .serializer import UserSerializer
from .models import User
# ユーザ作成のView(POST)
class UserRegister(generics.CreateAPIView):
permission_classes = (permissions.AllowAny,)
queryset = User.objects.all()
serializer_class = UserSerializer
@transaction.atomic
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
会員登録APIのURLを設定
from django.urls import re_path
from .views import UserRegister
urlpatterns = [
re_path(r'^register/$', UserRegister.as_view()),
]
全体のURL設定に会員登録APIのURLを追加
from django.urls import include, path
from rest_framework import routers
from likeX.tweet 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')),
path('api/user/', include('likeX.user.urls')), # ←追加
]
reactで会員登録APIを実行する処理を追加
axisoをインストール
--save
がpackage.json
に保存するという意味であることを今日知った。。
npm install axios --save
会員登録APIを実行するJSを作成
bulletproof-react
にならってAPI実行のJSを作成。
bulletproof-react
では、DTOを作成していたが、Typescriptではないため断念。。
ゆくゆくはTypescriptにも移行したい。
import axios from 'axios';
import { API_URL } from '../../../config';
export const registerUser = (data) => {
const jsonData = JSON.stringify(data);
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const url = `${API_URL}/api/user/register/`;
return axios.post(url, jsonData, config)
};
入力フォームのコンポーネントにAPI実行の処理を追加
chatGPT作のため、コメントが多い。。
usernameはdjango側では英数字で入力する、username
だが、フロント側では氏名になっていしまっているがここはゆくゆく直していく。
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
// FormDataから直接データを取得してオブジェクトに格納し、usernameをfirstNameとlastNameから構成
const registrationData = {
email: data.get('email'),
password: data.get('password'),
username: `${data.get('firstName')}${data.get('lastName')}`
};
// API 関数を使用してデータを送信
registerUser(registrationData)
.then((response) => {
console.log('Registration successful:', response);
// ここに成功時の処理を書く、例えばログインページへリダイレクト等
})
.catch((error) => {
console.error('Registration failed:', error);
// ここにエラー処理を書く、例えばエラーメッセージの表示等
});
};
画面から実行
CORSエラーが発生!!
(CORSエラーが発生しても登録自体はできているぽい。。)
Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/user/register/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORSエラーの解消
インストール
django-cors-headers
をvenvに追加。
設定の変更
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # ←CommonMiddlewareの上に追加
'django.middleware.common.CommonMiddleware',
]
# すべてのオリジンからのアクセスを許可する場合
CORS_ALLOW_ALL_ORIGINS = False
# 特定のオリジンだけを許可する場合
CORS_ALLOWED_ORIGINS = [
'http://localhost:3000', # Reactなどのフロントエンドが動作しているオリジン
]
# 特定のオリジンでのクッキーを許可する場合(認証を伴う場合など)
CORS_ALLOW_CREDENTIALS = True
再実行して、CORSエラーが発生していないことを確認。
感想
1日2時間程度で試行錯誤しながら記事も書きながらだと、なかなか思うように進まない。。
どこかのタイミングで知識の整理とコードの整理をしたい。
やると決めたからにはやる!