0
1

個人開発記録 2024/04/30~2024/05/2

Posted at

目的

  • とにかくやりきることが一番の目的
  • 毎日発信することで、発信する習慣作り
  • 個人開発をやりきることで、実績作り

開発するもの

X(旧Twitter)のパクリ

構成

  • バックエンド
    • python
    • django REST framework
  • DB
    • postgreSQL
  • フロントエンド
    • React

本編

前回会員登録画面の表示ができたので、会員登録APIの作成とreactから会員登録APIを実行するところを作成する。

djangoで会員登録APIの作成をする

userアプリを作成する

この記事tweetアプリは作成した。
それとは別にuserを作成することで、機能を分ける。

django-admin startapp user

設定を追加

likeX/settings.py
INSTALLED_APPS = [
    'likeX.user.apps.UserConfig',
]

Userモデルの作成

tweetのmodels.pyから移設。

/likeX/user/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が適用されないため、以下の設定を追加。

likeX/settings.py
AUTH_USER_MODEL = 'user.User'

すでに作成済みのテーブルをすべて削除し、マイグレーションを実行。
こうすることで、作成済みのdjango.contrib.authのテーブルが削除され、Userのテーブルが認証系のテーブルとして適用される。

python manage.py migrate

serializer,viewの作成

/likeX/user/serializer.py
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
/likeX/user/views.py
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を設定

/likeX/user/urls.py
from django.urls import re_path
from .views import UserRegister

urlpatterns = [
    re_path(r'^register/$', UserRegister.as_view()),
]

全体のURL設定に会員登録APIのURLを追加

/likeX/urls.py
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をインストール

--savepackage.jsonに保存するという意味であることを今日知った。。

npm install axios --save

会員登録APIを実行するJSを作成

bulletproof-reactにならってAPI実行のJSを作成。
bulletproof-reactでは、DTOを作成していたが、Typescriptではないため断念。。
ゆくゆくはTypescriptにも移行したい。

/src/features/auth/api/register.js
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だが、フロント側では氏名になっていしまっているがここはゆくゆく直していく。

/src/features/auth/components/RegisterForm.js
  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);
        // ここにエラー処理を書く、例えばエラーメッセージの表示等
      });
  };

画面から実行

image.png

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時間程度で試行錯誤しながら記事も書きながらだと、なかなか思うように進まない。。
どこかのタイミングで知識の整理とコードの整理をしたい。
やると決めたからにはやる!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1