-
django signup FBVProject using python/Cloning Airbnb 2021. 3. 1. 10:56
url 설정
config/urls.py
urlpatterns = [ path("users", include("users.urls", namespace="users")), ]
users/urls.py
from django.urls import path from . import views app_name = "users" urlpatterns = [path("signup/", views.signUp, name="signup")]
{% url %}
url template tag를 이용해서 signup page로 갈 수 있게 한다. {% url 'users:signup' %}은 /users/signup과 같다.
FBV(Function Based View)
users/views.py
FBV에서는 if 문으로 GET method 요청이 왔을 때와 POST method 요청이 왔을 때를 구분한다. GET은 page를 보여주고 POST는 client로부터 온 data를 처리한다.
from django.shortcuts import render, redirect, reverse from django.core.exceptions import ValidationError from . import models def signUp(request): if request.method == "GET": genders = models.User.GENDER_CHOICES languages = models.User.LANGUAGE_CHOICES currencies = models.User.CURRENCY_CHOICES choices = { "genders": genders, "languages": languages, "currencies": currencies, } return render(request, "pages/users/signup.html", context={**choices}) elif request.method == "POST": email = request.POST.get("email") if email is None: return redirect(reverse("users:signup")) try: # If a registered user with the email exists, raise error models.User.objects.get(email=email) raise ValidationError("User already exists") except models.User.DoesNotExist: password = request.POST.get("password") if password is None: return redirect(reverse("users:signup")) password1 = request.POST.get("password1") if password1 is None: return redirect(reverse("users:signup")) # If password doesn't match, raise error if password != password1: raise ValidationError("Password confirmation does not match") user = models.User.objects.create_user( username=email, email=email, password=password1 ) avatar = request.FILES.get("avatar") if avatar is not None and avatar != "": user.avatar = avatar first_name = request.POST.get("first_name") if first_name is not None: user.first_name = first_name last_name = request.POST.get("last_name") if last_name is not None: user.last_name = last_name gender = request.POST.get("gender") if gender is not None: user.gender = gender language = request.POST.get("language") if language is not None: user.language = language currency = request.POST.get("currency") if currency is not None: user.currency = currency birthdate = request.POST.get("birthdate") if birthdate is not None: user.birthdate = birthdate superhost = bool(request.POST.get("superhost")) if superhost is not None: user.superhost = superhost bio = request.POST.get("bio") if bio is not None: user.bio = bio user.save() return redirect(reverse("core:home")) except ValidationError as error: print(error) return redirect("core:home")
templates
pages/users/signup.html
<form> tag에 enctype="multipart/form-data" attribute가 있다. django가 file을 업로드할 때 사용하는 속성이다. views.py에서는 request.FILES.get()으로 업로드하는 file에 접근할 수 있다.
{% csrf_token %}은 csrf 공격을 막기 위한 token이다. django는 보안이 뛰어나기 때문에 {% csrf_token %} tag를 사용하지 않으면 submit이 안 된다. csrf 공격의 보안은 절대 client를 신뢰하지 않는 것으로 시작한다. 즉, 이 token 값을 가지지 않은 브라우저 요청은 받아들이지 않는다.
{% extends 'base.html' %} {% block page_title %} Sign Up {% endblock page_title %} {% block search-bar %} <div></div> {% endblock search-bar %} {% block content %} <div class="background"> <div class="wrap"> <form action="{% url 'users:signup' %}" method="post" class="form" enctype="multipart/form-data"> {% csrf_token %} <div class="form_input rounded-tl-lg rounded-tr-lg"> <input type="text" placeholder="First name" required class="w-full" name="first_name"> </div> <div class="form_input"> <input type="text" placeholder="Last name" required class="w-full" name="last_name"> </div> <div class="form_input"> <input type="email" placeholder="Email" required class="w-full" name="email"> </div> <div class="form_input"> <input type="password" placeholder="Password" required class="w-full" name="password"> </div> <div class="form_input"> <input type="password" placeholder="Confirm password" required class="w-full" name="password1"> </div> <div class="form_input"> <label for="id_avatar" class="text-lg font-bold">Avatar</label> <input type="file" name="avatar" accept="image/*" id="id_avatar"> </div> <div class="form_input"> <textarea name="bio" cols="40" rows="10" placeholder="Bio" class="resize-none" id="id_bio"></textarea> </div> <div class="select"> <label for="id_gender">Gender:</label> <select name="gender" id="gender"> {% for key, value in genders %} <option value="{{value}}"> {{value}} </option> {% endfor %} </select> </div> <div class="select"> <label for="{{form.language.id_for_label}}">Language:</label> <select name="language" id="language"> {% for key, value in languages %} <option value="{{value}}"> {{value}} </option> {% endfor %} </select> </div> <div class="select"> <label for="{{form.currency.id_for_label}}">Currency:</label> <select name="currency" id="currency"> {% for key, value in currencies %} <option value="{{value}}"> {{value}} </option> {% endfor %} </select> </div> <div class="birthdate rounded-br-xl rounded-bl-lg"> <label for="birthdate">Birthdate:</label> <input type="date" id="birthdate" name="birthdate"> </div> <button class="form_button">Submit</button> </form> </div> </div> {% endblock content %}
참고 자료
- 노마드 코더의 Airbnb 클론 강의
- ValidationError
- file upload
- {% csrf_token %}
소스 코드
github.com/zpskek/airbnb-clone-v3/commit/bc0926bc323c126ca56f4489b643c2016c23819d
'Project using python > Cloning Airbnb' 카테고리의 다른 글
django signup CBV (0) 2021.03.01 django signup FBV using forms.py (0) 2021.03.01 tailwind customzing (0) 2021.02.28 tailwind css @apply (0) 2021.02.28 tailwindcss with gulp (0) 2021.02.28