FrameWork/FastAPI
회원가입
mansoorrr
2024. 6. 20. 22:56
회원가입, 로그인, 로그아웃은 웹페이지에서 가장 중요한 부분중에 하나. 이거 할줄알면 다 안다고도 할 수 있음.
[ User model 만들기 ]
- User테이블이 많은 정보를 갖게 할 수 있지만 딱 필요한 정보만 가져오려 함
- User테이블은 id, username, password, email 네가지 변수를 갖는다고 정의
- 모델 정의 후 > alembic revision --autogenerate > alembic upgrade heade
// models.py
class User(Base):
__tablename__= "user"
id = Column(Integer, primary_key=True) #pk
username = Column(String, nullable=False, unique=True)
password = Column(String, nullable=False)
email = Column(String, nullable=False, unique=True)
[Navigation Bar 수정 및 회원가입 Component 생성]
1. Navigation Bar 수정
- Navigation.Svelte에 회원가입, 로그인 버튼 만들어줌
- use:link를 이용해 동적 페이지 지정
<script>
import {link} from 'svelte-spa-router';
</script>
<...생략...>
<span class="nav-button">
//프론트상의 dom경로 지정
<a use:link href="/user-create">회원가입</a>
</span>
<span class="nav-button">
//프론트상의 dom경로 지정
<a use:link href="/login">로그인</a>
</span>
2. UserCreate Component 생성
- localhost:5173/#/user-create로 이동했을때 보여질 화면 생성
- User모델과 달리 회원가입시에는 사용자이름, 비밀번호, 비밀번호확인, 이메일을 입력하게 함
<script>
import {link} from 'svelte-spa-router';
import {push} from 'svelte-spa-router';
import fastapi from '../lib/api';
import Error from '../components/Error.svelte';
//화면을 통해 받을 값들 변수초기화
let username = '';
let password1 = '';
let password2 = '';
let email = '';
let error = {detail:[]};
//회원가입 버튼 눌렀을때 실행될 함수
function postUser(event) {
event.preventDefault();
const url = '/api/user/create';
let params = {
"username": username,
"password1": password1,
"password2": password2,
"email": email,
}
fastapi('post', url, params,
(json) => {
push('/')
error = {detail:[]}
},
(json_error) => {
error = json_error
}
)
}
</script>
<div class="container">
<h3 class="border-bottom mt-3 py-3">회원가입</h3>
// 에러컴포넌트
<Error error={error}/>
<form action="post">
<div class="mb-3">
<label for="username">이름</label>
<input type="text" class="form-control" bind:value={username}>
</div>
<div class="mb-3">
<label for="password1">비밀번호</label>
<input type="text" class="form-control" bind:value={password1}>
</div>
<div class="mb-3">
<label for="password2">비밀번호 확인</label>
<input type="text" class="form-control" bind:value={password2}>
</div>
<div class="mb-3">
<label for="email">이메일</label>
<input type="text" class="form-control" bind:value={email}>
</div>
</form>
<button class="btn btn-dark" on:click={postUser}>회원가입</button>
<a use:link href="/" class="btn btn-secondary">취소</a>
</div>
[App.svelte에 회원가입Component추가]
- 만든 UserCreate.svelte를 App에 등록하여 라우팅 시 나타날 수 있도록 함
// App.svelte
<script>
import UserCreate from "./routes/UserCreate.svelte";
import Login from "./routes/Login.svelte";
</script>
const routes = {
"/": Home,
"/detail/:question_id": Detail,
"/question-create": QuestionCreate,
"/user-create": UserCreate, //추가
"/login": Login, //추가
}
[router 만들기 및 main에 등록]
- prefix=/api/user로 설정, routing은 /create로 설정
- 회원가입 정보는 post로 들어와야 함(보안문제)
- post를 통해 front에서 back으로 데이터를 보내기 위해서는 form을 거쳐야 함
- 이를 위해 user_schema.py에 UserCreate클래스(폼)를 만들어 적용
- UserCreate클래스의 유효성 검사
- 빈값입력할 경우 안되게: @field_validator 사용 > not_empty()
- 비밀번호 1과 2가 같은지 검사: password_match()
#---------- domain/user/user_shcema.py
from pydantic import BaseModel, EmailStr, field_validator
from pydantic_core.core_schema import FieldValidationInfo
from sqlalchemy import ValuesBase
# 화면에서 전달된 값이 아래 스키마를 통해 유효성 검사가 됨
class UserCreate(BaseModel):
username: str
password1: str
password2: str
email: EmailStr
# 빈값 안됨
@field_validator('username', 'password1', 'password2', 'email')
def not_empty(cls, v):
if not v or not v.strip():
raise ValueError('빈값은 안되요')
return v
#비밀번호1과 비밀번호2 같은지 유효성 검사
@field_validator("password2")
def password_match(cls, v, info: FieldValidationInfo):
if "password1" in info.data and v != info.data['password1']:
raise ValueError('비밀번호가 일치하지 않습니다')
return v
# ---------- domain/user/user_router.py
from fastapi import APIRouter
from domain.user import user_schema
router = APIRouter(prefix="/api/user")
@router.post('/create')
def user_create(user_create:user_schema.UserCreate, # 위에서 만든 녀석이 여기 들어감
db:Session=Depends(get_db),
):
# user객체를 만들때 폼(스키마)에서 유효성 검사를 마친 데이터가 사용됨
user = User(username=user_create.username, pasasword=user_ceate.password, email=user_create.email)
db.add(user)
db.commit()
#---------- main.py
app.include_router(user_router.router) #user
[구동확인]