Django2 (14. 리팩토링(form과 모델 분리)) feat.페스트캠퍼스

min seung moon·2021년 3월 19일
0

Django

목록 보기
30/37

간단한 리팩토링!

1. fcuser의 forms.py에 있는 def clean을 리팩토링!

01. RegisterForm

from django import forms
from .models import Fcuser
from django.contrib.auth.hashers import check_password, make_password

class RegisterForm(forms.Form):
    email = forms.EmailField(
        error_messages={
            'required': '이메일을 입력해주세요'
        },
        max_length=64, label='이메일'
    )
    password = forms.CharField(
        error_messages={
            'required': '비밀번호를 입력해주세요'
        },
        widget=forms.PasswordInput, label='비밀번호'
    )
    re_password = forms.CharField(
        error_messages={
            'required': '비밀번호를 입력해주세요'
        },
        widget=forms.PasswordInput, label='비밀번호확인'
    )

    # clean을 override를 해서 validate 동작을 완성
    def clean(self):
        cleaned_data = super().clean()
        email = cleaned_data.get('email')
        password = cleaned_data.get('password')
        re_password = cleaned_data.get('re_password')

        if password and re_password:
            if password != re_password:
                self.add_error('password', '비밀번호가 서로 다릅니다')
                self.add_error('re_password', '비밀번호가 서로 다릅니다')
            # 모델을 저장하는 부분도 같이 작성하였다(조건문이 있다보니)
            # 이렇게 작성하지 않고 분리를 한다
            # clean은 오직 유효성 검사만!
            # 이 아래 코드는 없어야 한다
            else:
                fcuser = Fcuser(
                    email=email,
                    password=make_password(password)
                )
                fcuser.save()


class LoginForm(forms.Form):
    email = forms.EmailField(
        error_messages={
            'required': '이메일을 입력해주세요'
        },
        max_length=64, label='이메일'
    )
    password = forms.CharField(
        error_messages={
            'required': '비밀번호를 입력해주세요'
        },
        widget=forms.PasswordInput, label='비밀번호'
    )

    # validate
    def clean(self):
        cleaned_data = super().clean()  # 값이 없으면 에러 전달
        email = cleaned_data.get('email')
        password = cleaned_data.get('password')

        if email and password:
            try:
                fcuser = Fcuser.objects.get(email=email)
            except Fcuser.DoesNotExist:
                self.add_error('email', '아이디가 없습니다')
                return
            if not check_password(password, fcuser.password):
                self.add_error('password', '비밀번호를 틀렸습니다')
            # 비밀번호가 맞았을 때
            else:
                # 성공한 지점
                # form객체 안에 email attribute key전달
                # 이곳에 입력한것이 views.py {'email': request.session.get('user')})이렇게 사용가능
                self.email = fcuser.email

  • 회원 가입 부터 삭제!

    • forms.py에서 모델 작업 삭제
    from django import forms
    from .models import Fcuser
    from django.contrib.auth.hashers import check_password
    
    class RegisterForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
      re_password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호확인'
      )
    
      # clean을 override를 해서 validate 동작을 완성
      def clean(self):
          cleaned_data = super().clean()
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
          re_password = cleaned_data.get('re_password')
    
          if password and re_password:
              if password != re_password:
                  self.add_error('password', '비밀번호가 서로 다릅니다')
                  self.add_error('re_password', '비밀번호가 서로 다릅니다')
    class LoginForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
    
      # validate
      def clean(self):
          cleaned_data = super().clean()  # 값이 없으면 에러 전달
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
    
          if email and password:
              try:
                  fcuser = Fcuser.objects.get(email=email)
              except Fcuser.DoesNotExist:
                  self.add_error('email', '아이디가 없습니다')
                  return
              if not check_password(password, fcuser.password):
                  self.add_error('password', '비밀번호를 틀렸습니다')
              # 비밀번호가 맞았을 때
              else:
                  # 성공한 지점
                  # form객체 안에 email attribute key전달
                  # 이곳에 입력한것이 views.py {'email': request.session.get('user')})이렇게 사용가능
                  self.email = fcuser.email
    

    • fcuser의 views.pu에 있는 RegisterView수정
    from django.shortcuts import render, redirect
    from django.views.generic.edit import FormView
    from .forms import RegisterForm, LoginForm
    from django.contrib.auth.hashers import make_password
    from .models import Fcuser
    # Create your views here.
    
    # index.html 연결 뷰
    def index(request):
      return render(request, 'index.html', {'email': request.session.get('user')})
      
    
    class RegisterView(FormView):
      # html file
      template_name = 'register.html'
      # forms.py에 있는 forms
      form_class = RegisterForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/login'
    
      # login view에서 사용햇던 함수를 오버라이딩
      # form_valid는 유효성 검사가 끝나고 호출된다
      # 유효성 검사 후의 추후 작업은 여거시 동작 시킨다
      def form_valid(self, form):
          fcuser = Fcuser(
              email=form.data.get('email'),
              password=make_password(form.data.get('password'))
          )
          fcuser.save()
    
          return super().form_valid(form)
    
    class LoginiView(FormView):
      # html file
      template_name = 'login.html'
      # forms.py에 있는 forms
      form_class = LoginForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/'
    
      # 유효성 검사가 끝났을 때, 로그인이 정상적으로 되었을 때
      def form_valid(self, form):
          self.request.session['user'] = form.email
    
          return super().form_valid(form)
    def logout(request):
      if 'user' in request.session:
          del(request.session['user'])
    
      return redirect('/')

    • 정상적으로 작동하는지 확인!


    • level도 있으니 views.py에 level도 자동적으로 'user'로 들어갈 수 있도록 수정!
    from django.shortcuts import render, redirect
    from django.views.generic.edit import FormView
    from .forms import RegisterForm, LoginForm
    from django.contrib.auth.hashers import make_password
    from .models import Fcuser
    # Create your views here.
    
    # index.html 연결 뷰
    def index(request):
      return render(request, 'index.html', {'email': request.session.get('user')})
      
    
    class RegisterView(FormView):
      # html file
      template_name = 'register.html'
      # forms.py에 있는 forms
      form_class = RegisterForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/login'
    
      # login view에서 사용햇던 함수를 오버라이딩
      # form_valid는 유효성 검사가 끝나고 호출된다
      # 유효성 검사 후의 추후 작업은 여거시 동작 시킨다
      def form_valid(self, form):
          fcuser = Fcuser(
              email=form.data.get('email'),
              password=make_password(form.data.get('password')),
              level = 'user'
          )
          fcuser.save()
    
          return super().form_valid(form)
    
    class LoginiView(FormView):
      # html file
      template_name = 'login.html'
      # forms.py에 있는 forms
      form_class = LoginForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/'
    
      # 유효성 검사가 끝났을 때, 로그인이 정상적으로 되었을 때
      def form_valid(self, form):
          self.request.session['user'] = form.email
    
          return super().form_valid(form)
    def logout(request):
      if 'user' in request.session:
          del(request.session['user'])
    
      return redirect('/')

02. LoginForm

  • clean에 있는 최하단 self.email = fcuser.email로 저장한느 부분을 리팩토링!

    from django import forms
    from .models import Fcuser
    from django.contrib.auth.hashers import check_password
    
    class RegisterForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
      re_password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호확인'
      )
    
      # clean을 override를 해서 validate 동작을 완성
      def clean(self):
          cleaned_data = super().clean()
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
          re_password = cleaned_data.get('re_password')
    
          if password and re_password:
              if password != re_password:
                  self.add_error('password', '비밀번호가 서로 다릅니다')
                  self.add_error('re_password', '비밀번호가 서로 다릅니다')
    class LoginForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
    
      # validate
      def clean(self):
          cleaned_data = super().clean()  # 값이 없으면 에러 전달
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
    
          if email and password:
              try:
                  fcuser = Fcuser.objects.get(email=email)
              except Fcuser.DoesNotExist:
                  self.add_error('email', '아이디가 없습니다')
                  return
              if not check_password(password, fcuser.password):
                  self.add_error('password', '비밀번호를 틀렸습니다')
              # 비밀번호가 맞았을 때
              else:
                  # 성공한 지점
                  # form객체 안에 email attribute key전달
                  # 이곳에 입력한것이 views.py {'email': request.session.get('user')})이렇게 사용가능
                  self.email = fcuser.email
    

    • forms.py 수정
    from django import forms
    from .models import Fcuser
    from django.contrib.auth.hashers import check_password
    
    class RegisterForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
      re_password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호확인'
      )
    
      # clean을 override를 해서 validate 동작을 완성
      def clean(self):
          cleaned_data = super().clean()
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
          re_password = cleaned_data.get('re_password')
    
          if password and re_password:
              if password != re_password:
                  self.add_error('password', '비밀번호가 서로 다릅니다')
                  self.add_error('re_password', '비밀번호가 서로 다릅니다')
    class LoginForm(forms.Form):
      email = forms.EmailField(
          error_messages={
              'required': '이메일을 입력해주세요'
          },
          max_length=64, label='이메일'
      )
      password = forms.CharField(
          error_messages={
              'required': '비밀번호를 입력해주세요'
          },
          widget=forms.PasswordInput, label='비밀번호'
      )
    
      # validate
      def clean(self):
          cleaned_data = super().clean()  # 값이 없으면 에러 전달
          email = cleaned_data.get('email')
          password = cleaned_data.get('password')
    
          if email and password:
              try:
                  fcuser = Fcuser.objects.get(email=email)
              except Fcuser.DoesNotExist:
                  self.add_error('email', '아이디가 없습니다')
                  return
              if not check_password(password, fcuser.password):
                  self.add_error('password', '비밀번호를 틀렸습니다')
              # 비밀번호가 맞았을 때

    • views.py 수정!(LoginiView)
    from django.shortcuts import render, redirect
    from django.views.generic.edit import FormView
    from .forms import RegisterForm, LoginForm
    from django.contrib.auth.hashers import make_password
    from .models import Fcuser
    # Create your views here.
    
    # index.html 연결 뷰
    def index(request):
      return render(request, 'index.html', {'email': request.session.get('user')})
      
    
    class RegisterView(FormView):
      # html file
      template_name = 'register.html'
      # forms.py에 있는 forms
      form_class = RegisterForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/login'
    
      # login view에서 사용햇던 함수를 오버라이딩
      # form_valid는 유효성 검사가 끝나고 호출된다
      # 유효성 검사 후의 추후 작업은 여거시 동작 시킨다
      def form_valid(self, form):
          fcuser = Fcuser(
              email=form.data.get('email'),
              password=make_password(form.data.get('password')),
              level = 'user'
          )
          fcuser.save()
    
          return super().form_valid(form)
    
    class LoginiView(FormView):
      # html file
      template_name = 'login.html'
      # forms.py에 있는 forms
      form_class = LoginForm
      # 정상적으로 값이 처리가 되었을 때 url이동
      success_url = '/'
    
      # 유효성 검사가 끝났을 때, 로그인이 정상적으로 되었을 때
      # 비밀번호가 맞았을 때, 성공한 지점
      # form객체 안에 email attribute key전달
      # 이곳에 입력한것이 views.py {'email': request.session.get('user')})이렇게 사용가능
      def form_valid(self, form):
          self.request.session['user'] = form.data.get('email')
    
          return super().form_valid(form)
    def logout(request):
      if 'user' in request.session:
          del(request.session['user'])
    
      return redirect('/')

    • 실행해보기!

2. Order 리팩토링(트랜잭션 처리)

  • order에 forms.py의 RegisterForm def clean
from django import forms
from .models import Order
from product.models import Product
from fcuser.models import Fcuser
# transaction 인터페이스
from django.db import transaction


class RegisterForm(forms.Form):
    # 생성자함수
    # requst에 전달하기 위해서 생성자 함수를 생성
    # product views의 productDetaile에서 form을 생성하는 부분이 있습니다!
    # 그리고 order의 views.py에서 request를 처리한다
    def __init__(self, request, *args, **kwargs):
        # 기존에 있던 생성자를 사용할 수 있도록 super()에서 불러온다!
        super().__init__(*args, **kwargs)
        self.request = request

    quantity = forms.IntegerField(
        error_messages={
            'required': '수량을 입력해주세요.'
        }, label='수량'
    )
    # 실제로 입력받는 값이 아니라 선택한 상품의 아이디를 받아옴
    # widget=forms.HiddenInput
    product = forms.IntegerField(
        error_messages={
            'required': '재고를 입력해주세요.'
        }, label='재고', widget=forms.HiddenInput
    )
    # validate

    def clean(self):
        cleaned_data = super().clean()
        quantity = cleaned_data.get('quantity')
        product = cleaned_data.get('product')
        # 사용자 정보!, requst.session에 접근이 필요!
        fcuser = self.request.session.get('user')

        if quantity and product and fcuser:
            # 이렇게 with으로 감싸서 atomic()으로 묶어주게 되면
            # with안에서 일어나는 모든 데이터베이스 관련 동작들은
            # 트랜잭션으로 처리
            with transaction.atomic():
                prod = Product.objects.get(pk=product)
                order = Order(
                    quantity=quantity,
                    product=Product.objects.get(pk=product),
                    fcuser=Fcuser.objects.get(email=fcuser)
                )
                order.save()
                # 수량만큼 재고에서 차감
                prod.stock -= quantity
                prod.save()
        # 실패했을 경우에
        # 템플릿 이름이 지정되지 않아 이대로면 오류가 난다
        # 주문하기 페이지를 따로 만들지 않기 때문에 템플릿을 만들필요는 없다!
        # Order의 views에 함수를 만들고 추가하기!(self.product = product)
        else:
            self.product = product
            self.add_error('quantity', '값이 없습니다')
            self.add_error('product', '값이 없습니다')

  • forms.py에서 복사하기!
            # 이렇게 with으로 감싸서 atomic()으로 묶어주게 되면
            # with안에서 일어나는 모든 데이터베이스 관련 동작들은
            # 트랜잭션으로 처리
            with transaction.atomic():
                prod = Product.objects.get(pk=product)
                order = Order(
                    quantity=quantity,
                    product=Product.objects.get(pk=product),
                    fcuser=Fcuser.objects.get(email=fcuser)
                )
                order.save()
                # 수량만큼 재고에서 차감
                prod.stock -= quantity
                prod.save()

  • views.py의 OrderCreate에 def form_valid()설정
from django.shortcuts import render, redirect
from .forms import RegisterForm
from django.views.generic.edit import FormView
from django.views.generic import ListView
from .models import Order
# decorator 설정, 클래스에 바로 지정 가능
from django.utils.decorators import method_decorator
from fcuser.decorator import login_required
# Create your views here.
# transaction 인터페이스
from django.db import transaction
from product.models import Product
from fcuser.models import Fcuser


@method_decorator(login_required, name='dispatch')
class OrderCreate(FormView):
    # 화면은 따로 구연할 필요 없기 때문에 template_name = 은 생략
    form_class = RegisterForm
    success_url = '/product/'

    def form_valid(self, form):
        # 이렇게 with으로 감싸서 atomic()으로 묶어주게 되면
        # with안에서 일어나는 모든 데이터베이스 관련 동작들은
        # 트랜잭션으로 처리
        with transaction.atomic():
            prod = Product.objects.get(pk=form.data.get('product'))
            order = Order(
                quantity=form.data.get('quantity'),
                product=prod,
                fcuser=Fcuser.objects.get(
                    email=self.request.session.get('user'))
            )
            order.save()
            # 수량만큼 재고에서 차감
            prod.stock -= int(form.data.get('quantity'))
            prod.save()
        return super().form_valid(form)

    # 실패했을 때 redirect하는 함수
    # 숫자형이기 때문에 문자열로 변경해주어야 한다
    def form_invalid(self, form):
        return redirect('/product/'+str(form.data.get('product')))

    # form을 생성할 때 어떤 인자값을 전달해서 만들건지를 결정하는 함수
    # formview안에서도request를 전달할 수 있게 해주어야 한다!
    def get_form_kwargs(self, **kwargs):
        kw = super().get_form_kwargs(**kwargs)
        kw.update({
            # 기존에 있던 인자 값에다가 request를 포함하겠다!
            'request': self.request
        })
        return kw


# 클래스 뷰에서 URL에 접근했을 클래스 뷰를 호출할 때 dispatch가 호출(실행)된다
# def dispatch()
# decorator를 지정할려면 원래 dispatch 함수를 만들어서 decorator를 지정해야 된다
# 장고안에 있는 method_decorator를 지정하면 바로 지정 가능 하다
@method_decorator(login_required, name='dispatch')
class OrderList(ListView):
    template_name = 'order.html'
    context_object_name = 'order_list'

    def get_queryset(self, **kwargs):
        queryset = Order.objects.filter(
            fcuser__email=self.request.session.get('user'))
        return queryset

  • order의 forms.py 완성하기!
    • else문을 if문으로 바꾸기!(부정)
from django import forms
from .models import Order
from product.models import Product
from fcuser.models import Fcuser


class RegisterForm(forms.Form):
    # 생성자함수
    # requst에 전달하기 위해서 생성자 함수를 생성
    # product views의 productDetaile에서 form을 생성하는 부분이 있습니다!
    # 그리고 order의 views.py에서 request를 처리한다
    def __init__(self, request, *args, **kwargs):
        # 기존에 있던 생성자를 사용할 수 있도록 super()에서 불러온다!
        super().__init__(*args, **kwargs)
        self.request = request

    quantity = forms.IntegerField(
        error_messages={
            'required': '수량을 입력해주세요.'
        }, label='수량'
    )
    # 실제로 입력받는 값이 아니라 선택한 상품의 아이디를 받아옴
    # widget=forms.HiddenInput
    product = forms.IntegerField(
        error_messages={
            'required': '재고를 입력해주세요.'
        }, label='재고', widget=forms.HiddenInput
    )
    # validate

    def clean(self):
        cleaned_data = super().clean()
        quantity = cleaned_data.get('quantity')
        product = cleaned_data.get('product')
        # 사용자 정보!, requst.session에 접근이 필요!
        fcuser = self.request.session.get('user')

        # 실패했을 경우에
        # 템플릿 이름이 지정되지 않아 이대로면 오류가 난다
        # 주문하기 페이지를 따로 만들지 않기 때문에 템플릿을 만들필요는 없다!
        # Order의 views에 함수를 만들고 추가하기!(self.product = product)
        if not (quantity and product):
            self.add_error('quantity', '값이 없습니다')
            self.add_error('product', '값이 없습니다')

  • order의 views.py 완성하기!
from django.shortcuts import render, redirect
from .forms import RegisterForm
from django.views.generic.edit import FormView
from django.views.generic import ListView
from .models import Order
# decorator 설정, 클래스에 바로 지정 가능
from django.utils.decorators import method_decorator
from fcuser.decorator import login_required
# Create your views here.
# transaction 인터페이스
from django.db import transaction
from product.models import Product
from fcuser.models import Fcuser


@method_decorator(login_required, name='dispatch')
class OrderCreate(FormView):
    # 화면은 따로 구연할 필요 없기 때문에 template_name = 은 생략
    form_class = RegisterForm
    success_url = '/product/'

    def form_valid(self, form):
        # 이렇게 with으로 감싸서 atomic()으로 묶어주게 되면
        # with안에서 일어나는 모든 데이터베이스 관련 동작들은
        # 트랜잭션으로 처리
        with transaction.atomic():
            prod = Product.objects.get(pk=form.data.get('product'))
            order = Order(
                quantity=form.data.get('quantity'),
                product=prod,
                fcuser=Fcuser.objects.get(
                    email=self.request.session.get('user'))
            )
            order.save()
            # 수량만큼 재고에서 차감
            prod.stock -= form.data.get('quantity')
            prod.save()
        return super().form_valid(form)

    # 실패했을 때 redirect하는 함수
    # 숫자형이기 때문에 문자열로 변경해주어야 한다
    def form_invalid(self, form):
        return redirect('/product/'+str(form.data.get('product')))

    # form을 생성할 때 어떤 인자값을 전달해서 만들건지를 결정하는 함수
    # formview안에서도request를 전달할 수 있게 해주어야 한다!
    def get_form_kwargs(self, **kwargs):
        kw = super().get_form_kwargs(**kwargs)
        kw.update({
            # 기존에 있던 인자 값에다가 request를 포함하겠다!
            'request': self.request
        })
        return kw


# 클래스 뷰에서 URL에 접근했을 클래스 뷰를 호출할 때 dispatch가 호출(실행)된다
# def dispatch()
# decorator를 지정할려면 원래 dispatch 함수를 만들어서 decorator를 지정해야 된다
# 장고안에 있는 method_decorator를 지정하면 바로 지정 가능 하다
@method_decorator(login_required, name='dispatch')
class OrderList(ListView):
    template_name = 'order.html'
    context_object_name = 'order_list'

    def get_queryset(self, **kwargs):
        queryset = Order.objects.filter(
            fcuser__email=self.request.session.get('user'))
        return queryset

  • 실행해보기!



3. Product 리팩토링(forms.py 처리)

from django import forms
from .models import Product


class RegisterForm(forms.Form):
    name = forms.CharField(
        error_messages={
            'required': '상품명을 입력해주세요'
        },
        max_length=64, label='상품명'
    )
    price = forms.IntegerField(
        error_messages={
            'required': '상품가격을 입력해주세요'
        }, label='상품가격'
    )
    description = forms.CharField(
        error_messages={
            'required': '상품설명을 입력해주세요'
        }, label='상품설명'
    )
    stock = forms.IntegerField(
        error_messages={
            'required': '재고를 입력해주세요.'
        }, label='재고'
    )

    # validate
    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        price = cleaned_data.get('price')
        description = cleaned_data.get('description')
        stock = cleaned_data.get('stock')

        if name and price and description and stock:
            product = Product(
                name=name,
                price=price,
                description=description,
                stock=stock
            )
            product.save()

  • forms.py의 clean 수정
from django import forms
from .models import Product


class RegisterForm(forms.Form):
    name = forms.CharField(
        error_messages={
            'required': '상품명을 입력해주세요'
        },
        max_length=64, label='상품명'
    )
    price = forms.IntegerField(
        error_messages={
            'required': '상품가격을 입력해주세요'
        }, label='상품가격'
    )
    description = forms.CharField(
        error_messages={
            'required': '상품설명을 입력해주세요'
        }, label='상품설명'
    )
    stock = forms.IntegerField(
        error_messages={
            'required': '재고를 입력해주세요.'
        }, label='재고'
    )

    # validate
    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        price = cleaned_data.get('price')
        description = cleaned_data.get('description')
        stock = cleaned_data.get('stock')

        if not (name and price and description and stock):
            self.add_error('name', '값이 없습니다')
            self.add_error('price', '값이 없습니다')

  • views.py에 productcreate에 form_valid생성
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from django.views.generic.edit import FormView
from .models import Product
from .forms import RegisterForm
from order.forms import RegisterForm as OrderForm
from django.utils.decorators import method_decorator
from fcuser.decorator import admin_required
# Create your views here.


class ProductList(ListView):
    model = Product
    template_name = 'product.html'
    # object_list로 사용하기 싫으면 context_object_name으로 변경 가능
    context_object_name = 'product_list'


@method_decorator(admin_required, name='dispatch')
class ProductCreate(FormView):
    template_name = 'register_product.html'
    form_class = RegisterForm
    success_url = '/product/'

    def form_valid(self, form):
        product = Product(
            name=form.data.get('name'),
            price=form.data.get('price'),
            description=form.data.get('description'),
            stock=form.data.get('stock')
        )
        product.save()
        return super().form_valid(form)


class ProductDetail(DetailView):
    template_name = 'product_detail.html'
    # 어떤 모델이 아닌 쿼리셋을 지정
    # 필터를 통해서 보여질지 말지도 결정할 수 있다
    queryset = Product.objects.all()
    # template에서 사용할 변수명 지정
    context_object_name = 'product'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # Order의 forms의 생성자 함수!
        # 그리고 order의 views.py에서 request를 처리한다
        context['form'] = OrderForm(self.request)
        return context

  • 실행해보기!




정리

  • 실제로 코드를 작성할 때는 유효성 검사는 form이 form을 관리
  • form이 정상적으로 채워졌을 때 데이터를 저장할 때는 views.py의 form_valid함수를 사용!
profile
아직까지는 코린이!

0개의 댓글