[Django] clone instagram #7


登録APIの作成


私はajaxを通じて実際に会員に加入するAPIを作成します.passwordは暗号化され、DBに格納される.
暗号化には一方向/双方向があります.
この場合、一方向暗号化すると元の状態に戻ることはできません.
双方向暗号化後、そのまま「復号」することができます.
この場合、passwordなどは復号できないので、一方向暗号化を使用します!
前述のドラムユーザモデルでは、password基本関数が実質的に提供される.
この基本関数make_passwordを使用してpasswordを暗号化し、データベースに保存します.user/views.py
from django.contrib.auth.hashers import make_password
from rest_framework.response import Response
from .models import User


class Join(APIView):
    ...
    
    def post(self, request):
        # 회원가입
        email = request.data.get('email', None)
        nickname = request.data.get('nickname', None)
        name = request.data.get('name', None)
        password = request.data.get('password', None)

        # User DB 만들어 주기
        User.objects.create(email=email,
                            nickname=nickname,
                            name=name,
                            password=make_password(password),  # password가 암호화되어 저장
                            profile="default_profile.jpg")
        
        return Response(status=200)

「≪サブスクリプション|Subscription|ldap≫」ボタンをクリックしたイベントの作成

templates/join.html html
...
<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="email" class="form-control" id="input-email" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-email">휴대폰 번호 또는 이메일 주소</label>
</div>

<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="text" class="form-control" id="input-name" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-name">이름</label>
</div>

<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="text" class="form-control" id="input-nickname" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-nickname">닉네임</label>
</div>

<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="text" class="form-control" id="input-password" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-password">비밀 번호</label>
</div>

<button id="join-button" style="width: 300px; height: 32px; margin: auto; font-size: 14px; font-weight: bolder; margin-top: 8px;" type="button" class="btn btn-primary">가입</button>
...
js
$('#join-button').click(function(){  // 가입하기 버튼을 클릭하면

                let email = $('#input-email').val();
                let nickname = $('#input-nickname').val();
                let name = $('#input-name').val();
                let password = $('#input-password').val();

                console.log(email, nickname, name, password)
});
id値を設定し、Jクエリーを使用して登録ボタンをクリックするとデータを取得できます.

データサーバに送信

ajaxを使用して、含まれるデータが送信されます.templates/join.html js
$.ajax({
      url: "/user/join",
      data: {
              email : email,
              nickname : nickname,
              name : name,
              password : password
            },
      method: "POST",
      success: function (data) {
        console.log("성공");
        alert("회원가입 성공했습니다. 로그인을 해주세요.");
        location.replace('/user/login');
      },
      error: function (request, status, error) {
        console.log("에러");
      },
      complete: function() {
        console.log("완료");
      }
})
サーバーを実行し、ユーザー情報を入力し、会員入力ボタンをクリックすると、入力データがデータベースに格納されていることを確認できます.


ログインAPIの作成


作成会員が加入してからログインしたAPIを作成する
まずビューを作成します.user/views.py
class Login(APIView):
...
    def post(self, request):
        # 로그인
        email = request.data.get('email', None)
        password = request.data.get('password', None)

        user = User.objects.filter(email=email).first()  # email은 unique정보로, 있으면 무조건 1개이기 때문에 fist()를 사용해 첫번째 값만 꺼내온다.

        if user is None:  # 해당 이메일이 User 디비에 없는 경우 에러 반환
            return Response(status=400, data=dict(message="회원정보가 잘못되었습니다."))  # 에러메세지를 '없습니다가' 아닌 '잘못되었다고' 하는 이유는 해커에게 도움을 주지 않기 위해서

        if user.check_password(password):  # 해당 이메일이 User 디비에 있는 경우 password를 비교
            # todo 로그인 성공. 세션 or 쿠키에 넣음
            return Response(status=200)  # 비밀번호가 맞을 경우, 로그인 성공
        else:  # 비밀번호가 틀린경우, 에러메세지 반환
            return Response(status=404, data=dict(message="회원정보가 잘못되었습니다."))

ログインボタンをクリックするイベントの作成

templates/login.html html
...
<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="email" class="form-control" id="input-email" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-email">휴대폰 번호 또는 이메일 주소</label>
</div>

<div class="form-floating mb-3">
  <input style="width: 300px; height: 24px; margin: auto;" type="text" class="form-control" id="input-password" placeholder="[email protected]">
  <label style="font-size: 13px; padding: 4px 10px; margin-left: 30px; margin-top: 2px;" for="input-password">비밀 번호</label>
</div>

<button id="login-button" style="width: 300px; height: 32px; margin: auto; font-size: 14px; font-weight: bolder; margin-top: 8px;" type="button" class="btn btn-primary">로그인</button>
...
js
$('#login-button').click(function(){  // 가입하기 버튼을 클릭하면

    let email = $('#input-email').val();
    let password = $('#input-password').val();

    console.log(email, password)
});
idの値を設定した後、Jクエリーを使用して、ユーザーがログインボタンをクリックしたときにデータを取得できるようにします.

データサーバに送信

(email,password)を使用して、データを含むajaxサーバが送信される.templates/login.html js
$.ajax({
      url: "/user/login",
      data: {
              email : email,
              password : password
            },  
      method: "POST",
      success: function (data) {
        console.log("성공");
        alert("로그인 성공했습니다.");
        location.replace('/main');  // 로그인 성공시 main페이지로 이동
      },
      error: function (request, status, error) {
        console.log("에러");
      },
      complete: function() {
        console.log("완료");
      }
})
サーバーを実行し、適切なEメールとパスワードを入力すると、ログインを確認してホームページに戻ります.
7:36:10