ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • django signup FBV
    Project 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 %}

    참고 자료

    소스 코드

    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

    댓글

Designed by Tistory.