Dstargram project - 4

[ Dstargram project ]

  • 회원가입(Sign Up) 만들기

    • accounts/views.py 추가 작성

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      # accounts/views.py
      # 기존에 입력받는 뷰 - CreateView 상속 받아서
      # 상속받아서 만들면 커스텀이 힘들다.
      # 회원가입 -> User 모델에 값을 입력받는다.-> CreateView
      # 회원가입시 모델 필드 외에 추가 입력이 필요하다.
      # 커스텀 뷰를 하려면 함수형 뷰가 적절하겠다.

      from .forms import SignUpForm
      def signup(request):
      # 함수형 뷰에서는 매개변수 request가 꼭 있어야 한다.
      # Class Based View였다면 dispatch -> get, post
      if request.method == "POST":
      # Todo : 입력 받은 내용을 이용해서 회원 객체 생성
      # 입력받은 내용 확인하기
      # 모델 폼을 이용해서 코드를 간결하게 바꾼다.
      # validation - 아이디가 중복되는지, 아이디가 한글은 아닌지

      signup_form = SignUpForm(request.POST) # 폼에 내용이 채워져 있는 형태로 출력됨

      # form validation이 진행되지 않은 채로 저장하게 되기 때문에...
      if signup_form.is_valid():
      # 1. 저장하고 인스턴스 생성
      user_instance = signup_form.save(commit=False) # 해당 입력받은 정보를 가지고 인스턴스를 만들어줌
      # commit=False 옵션을 통해 데이터베이스에는 저장이 안되도록 함
      # 2. 패스워드 암호화 -> 저장
      # 폼이 가지고 있는 cleaned_data는 무엇인가? : 유효한 문자만 남긴 상태로 처리 과정을 거친 데이터
      # request.POST.get('password') <- 이런 방법으로 받지 않는다.
      user_instance.set_password(signup_form.cleaned_data['password'])
      user_instance.save()

      return render(request, 'accounts/signup_complete.html', {'username':user_instance.username})
      # username을 던져줌. 'username'이 html에서 쓰일 이름/ 뒤에 user_instance.username이 html로 넘기는 값

      # username = request.POST.get('username')
      # password = request.POST.get('password')
      # first_name = request.POST.get('first_name')
      # last_name = request.POST.get('last_name')
      # email = request.POST.get('email')
      # print(username, password, first_name, last_name, email)
      # # 회원 객체 생성하기
      # user = User()
      # user.username = username
      # # user.password = password # set_password()를 쓰지 않고 저장하면 암호화되지 않은채 저장된다.
      # user.set_password(password) # 비밀번호를 비밀번호화 시켜주는 메서드
      # user.first_name = first_name
      # user.last_name = last_name
      # user.email = email
      # user.save()
      else:
      # form 객체를 만들어서 전달
      # form에는 username, password만 입력 받으면 된다.

      signup_form = SignUpForm()
      # 1. 템플릿 불러오기
      # 2. 템플릿 렌더링하기
      # 3. HTTP Response하기
      return render(request, 'accounts/signup.html', {'form':signup_form}) # 변수값 전달 방법
    • accounts/forms.py 생성 및 작성

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      # accounts/forms.py
      # 모델 폼을 만드려면 2가지 필요하다.
      # 제네릭 뷰: 제네릭 뷰, 모델
      # 모델 폼 : 모델, 폼

      from django.contrib.auth.models import User
      from django import forms

      class SignUpForm(forms.ModelForm):

      password = forms.CharField(label='Password', widget=forms.PasswordInput) # 추가 필드

      password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)

      class Meta:
      model = User
      # fields에는 해당 모델에 대해 입력받을 필드들을 나열한다.
      # + 추가 필드도 포함될 수 있다. -> 필드 목록과 추가 필드가 겹치면 오버라이드(추가 필드의 우선순위가 높다.)
      # fields에 써준 순서대로 출력한다.
      fields = ['username','password','password2','first_name','last_name','email'] # 입력받을 필드명을 입력
      # fields = '__all__' # 전체 다 부르고 싶을 경우

      # Todo : 필드의 기본값, Placeholder 설정법, css Class 설정법법, validator 설정법법, help text 설정
      # Todo : 커스텀 필드 만드는 법

      # 비밀번호가 일치하지 않을 경우
      def clean_password2(self):
      cd = self.cleaned_data
      if cd['password'] != cd['password2']:
      raise forms.ValidationError('비밀번호가 일치하지 않습니다.')
      # 항상 해당 필드의 값을 리턴한다.
      return cd['password2']
    • accounts/urls.py 추가 작성

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      # accounts/urls.py
      from django.urls import path
      from django.contrib.auth.views import LoginView, LogoutView

      # 함수형 뷰 signup 추가
      from .views import UserList, FollowerList, FollowingList, FollowButton, signup

      app_name = 'accounts'

      urlpatterns = [
      path('user/list/', UserList.as_view(), name='user_list'),
      path('follow/<int:user_id>/', FollowButton.as_view(), name='follow_button'),
      path('follower/list/', FollowerList.as_view(), name='follower_list'),
      path('following/list/', FollowingList.as_view(), name='following_list'),
      path('singin/', LoginView.as_view(template_name='accounts/signin.html'), name='signin'),
      path('signout/', LogoutView.as_view(template_name='accounts/signout.html'), name='signout'),

      # signup 경로 추가
      path('signup/', signup, name='signup'), # 함수형 뷰는 이름만 쓴다.
      ]
    • templates 수정 및 작성

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      <!--// base.html //-->
      <li class="nav-item">
      <!--// signup에 대한 경로 추가 //-->
      <a class="nav-link" href="{% url 'accounts:signup' %}">Sign-up</a>
      </li>


      <!--// signup.html //-->
      <!--// 회원가입 페이지 //-->
      {% extends 'base.html' %}
      {% block title %}
      Sign Up
      {% endblock %}

      {% block content %}
      <div class="row">
      <div class="col"></div>
      <div class="col-6">
      <form action="" method="post">
      <div class="alert alert-info">Please enter your account information</div>
      {% csrf_token %}
      {{form.as_p}}
      <input type="submit" value="Sign Up" class="btn btn-outline-info">
      </form>
      </div>
      <div class="col"></div>
      </div>
      {% endblock %}


      <!--// signup_complete //-->
      <!--// 회원가입 완료 페이지 //-->
      {% extends 'base.html' %}
      {% block title %}
      SignUp Complete
      {% endblock %}

      {% block content %}
      <div class="row">
      <div class="col"></div>
      <div class="col-6">
      <div class="alert alert-success">{{username}} suceessfully signed up</div>
      <a href="{% url 'accounts:signin' %}" class="btn btn-outline-info">Move to Sign in</a>
      </div>
      <div class="col"></div>
      </div>
      {% endblock %}
  • heroku를 이용한 배포

    1. heroku 회원가입

      • heroku.com 접속
    2. heroku CLI 설치

      1
      $ sudo snap install --classic heroku
    3. 추가 모듈 설치

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      # 데이터베이스 관련 옵션을 변수로 쉽게 접근할 수 있게 해주는 유틸리티
      $ pip install dj-database-url

      # wsgi용 미들웨어 - 웹서버와 장고 사이에 다리
      $ pip install gunicorn

      # static 파일 서빙용 미들웨어
      $ pip install whitenoise

      # postgreSQL용 드라이버
      $ pip install psycopg2-binary
    4. 의존성 리스트 생성

      1
      $ pip freeze > requirements.txt
    5. heroku 로그인

      1
      2
      3
      4
      $ heroku login

      # 아무 키나 누르고 heroku 웹사이트로 이동해서 로그인하면 된다.
      >> heroku: Press any key to open up the browser to login or q to exit:
    6. 모듈 설정 - settings.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      # settings.py
      DEBUG = False # True에서 False로 수정
      ALLOWED_HOSTS = ['*']

      # whitenoise 항목 추가
      MIDDLEWARE = [
      'django.middleware.security.SecurityMiddleware',
      'django.contrib.sessions.middleware.SessionMiddleware',
      'django.middleware.common.CommonMiddleware',
      'django.middleware.csrf.CsrfViewMiddleware',
      'django.contrib.auth.middleware.AuthenticationMiddleware',
      'django.contrib.messages.middleware.MessageMiddleware',
      'django.middleware.clickjacking.XFrameOptionsMiddleware',
      'whitenoise.middleware.WhiteNoiseMiddleware',
      ]

      # dj_database_url 항목 추가
      import dj_database_url
      DATABASES['default'].update(dj_database_url.config(conn_max_age=500))

      # static root 추가
      STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    7. 파일 생성 및 추가

      • 프로젝트 최상단에서 만들기
      1. Procfile(확장자 없음) 생성

        1
        web: gunicorn config.wsgi
      2. runtime.txt 생성

        1
        python-3.7.0
      3. .gitignore(확장자 없음) 생성

        1
        2
        3
        4
        5
        *pyc
        *~
        /venv
        __pycache__
        db.sqlite3
    8. git 설정

      1
      2
      3
      4
      5
      $ git init

      $ git add -A .

      $ git commit -m "message"
    9. heroku app 만들기

      1
      $ heroku create [app_name]
    10. 업로드

      1
      $ git push heroku master
    11. DB 초기화

      1
      $ heroku run python manage.py migrate
    12. 관리자 계정 생성

      1
      $ heroku run python manage.py createsuperuser
    13. heroku 웹사이트로 이동하여 생성한 앱 이름을 클릭 후, Open app을 누른다.

      • 웹사이트가 잘 실행되는지 확인한다.
      • 관리자 사이트도 잘 실행되는지 확인한다.
Share