raek
2k
2019-05-26 02:37:36 작성 2019-05-26 14:47:16 수정됨
13
370

django + react 간단한 회원가입 구현 질문이요


안녕하세요 현재 프론트엔드는 react를 사용하고 서버는 django를 사용하는데

회원가입이 뭐가 문제인지 조건을 만족하고 signup을 누르면 자꾸 fail이 뜨는데

에러 내용이

2019-05-26 02:27:37,076 DEBUG member_manager.views testa13@gmail.com 12341234q

2019-05-26 02:27:37,089 DEBUG member_manager.views 'AnonymousUser' object has no attribute '_meta'

입니다.

어쩌다 한번은 success가 뜨긴 뜹니다.. 물론 페이지 이동은 안하네요..

작동하는 부분만 코드 짧게 넣었는데 한번 봐주시면 감사하겠습니다.


우선 리액트에는

service.js

PersonalInput.js ( 퍼스널인풋)

PersonalInputContanier.js (퍼스널인풋컨테이너)

personalInputReducer.js (퍼스널인풋리듀서) 가 있는데


그리고 django 에는

views.py

models.py

managers.py 가있는데 


참고로 저는 django 문제 같습니다.. react에서는 아무리봐도 에러를 못찾겠는데..


회원가입 코드가 작동되는 부분만 말씀드리면

리액트의

service.js 코드는 다음과 같습니다.

import axios from 'axios';
import Cookies from 'js-cookie';

export function registerRequest(email, passwd) {
    axios.post('http://localhost:8000/api/signup', {
        id: email,
        passwd: passwd
    })
    .then(function (response) {
        console.log(response.data.result)
        if(response.data.result == 'success')
            return 'success';
        else
            return 'fail';
    })
    .catch(function (error) {
        console.log(error);
        return 'fail';
    });
}


PersonalInput.js 코드는 이 부분만 보시면 됩니다.

저는 여기서 잘못된게 아닐까 생각됩니다..

{fail && ( <Header as='h3' block textAlign='center' color='red'> 회원 가입 실패! </Header>) }
{ <Button disabled={!check.enable_next} onClick={register} color='red' fluid size='large'>Sign Up</Button> }


PersonalInputContanier.js 코드는 이 부분만 보시면 됩니다.

여기서 분명히 success 값을 받으면 페이지 이동을 signup/2로 하는데 왜 안하는지 모르겠습니다.

register = (e) => {
        const { InputActions, email, password } = this.props;
        if (service.registerRequest(email, password)=='success')
            return <Redirect to='/signup/2' />
        else {
            InputActions.register_fail();
        }
    }


personalInputReducer.js  코드는 이부분만 보시면 됩니다.

const REGISTER_FAIL = 'signup/register_fail';
export const register_fail = createAction(REGISTER_FAIL);

const initialState = {
    email : '',
    password : '',
    pcheck : '',
    certification_number : '',
    sended : false,
    check_number : '1q2w3e', // 인증 확인 번호
    check : {
        email : false,
        password : false,
        pcheck : false,
        enable_next : false
    },
    fail : false,
    loading: false,
    message: '',
    errMessage: ''
};

// ~~~~~~~

[REGISTER_FAIL] : (state, action) => {
        return {
            ...state,
            fail : true,
        };
    },



마지막으로 django 에있는

views.py 코드는 다음과 같습니다 (import한건 에러가 없기 때문에 적지 않았습니다.)

참고로 여기서 프론트엔드로 return 해줄때.. 문제가 있는지 궁금합니다.

@csrf_exempt
def signup(request):
    try:
        body = json.loads(request.body)
        email = body['id']
        passwd = body['passwd']
        logger.debug('{} {}'.format(email, passwd))
        
        new_user = UserManager.create_user(email, passwd)
        login(request, new_user, backend='django.contrib.auth.backends.ModelBackend')
        return JsonResponse({'result': 'success'})
    except Exception as e:
        logger.debug(e)
        return JsonResponse({'result': 'fail'})


django의 models.py는

# 인증관련 주요모델 필드
from __future__ import unicode_literals

from django.db import models  
from django.core.mail import send_mail  
from django.contrib.auth.models import PermissionsMixin  
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from .managers import UserManager

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email'), unique=True)
    password = models.CharField(max_length=28)
    date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
    is_active = models.BooleanField(_('active'), default=True)
    is_superuser = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def is_staff(self):
        return self.is_superuser

    def email_user(self, subject, message, from_email=None, **kwargs):
        '''
        Sends an email to this User.
        '''
        send_mail(subject, message, from_email, [self.email], **kwargs)



django의 managers.py 에서는 이부분만 봐도 될거 같습니다.

def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('You must input email')
        
        User = get_user_model() # django 프로젝트가 사용하는 user모델을 가져온다
        if not (User.objects.filter(email=email).exists()):
            user = User.objects.create(email=email)
            user.set_password(password)
            user.save()
        else:
            return None
        return user


어디가 문제인지 알려주시면 정말 감사하겠습니다.

0
0
  • 답변 13

  • 우르르응
    148
    2019-05-26 08:29:11 작성 2019-05-26 08:29:28 수정됨

    어쩌다 성공하는 경우는 언제일까요??

    언제 성공하고 실패하는지를 기준으로 해결할 수 있지 않을까요??


    'AnonymousUser' object has no attribute '_meta'

    이렇게 구글링해보면 관련 글이 많이 나오는걸로 봐서 제 생각에는 특정 라이브러리에 문제가 있는것 같네요.

    찾아보니 authenticate()에서 문제가 발생했는데, 질문자님도 해당 함수 작성 부분이 있나요?


    제가 Django는 잘 몰라서 참고자료 남깁니다.

    https://beomi.github.io/2017/02/02/Django-CustomAuth/

    0
  • 우르르응
    148
    2019-05-26 08:35:34
    찾아보니 views.py 파일에
    login(request, new_user, backend='django.contrib.auth.backends.ModelBackend'
    django.contrib~~~
    이 부분 settings.py파일에 있어야 하지 않을까요??
    0
  • raek
    2k
    2019-05-26 14:35:13 작성 2019-05-26 14:36:14 수정됨

    우르르응

    답변정말 감사합니다 ㅠㅠ

    말씀하신데로 
    django.contrib.auth.backends.ModelBackend    가 settings.py 에 없네요..

    주신 링크를 참고하니까

    # settings.py
    AUTHENTICATION_BACKENDS = [
        'my_user.my_auth.UserBackend', # 우리가 만든 AUTH를 먼저 검사
        'django.contrib.auth.backends.ModelBackend', # Django가 관리하는 AUTH
    ]

    이렇게  등록하던데

    'my_user.my_auth.UserBackend' 는 구현을 안해서 이건 제외하고

    django.contrib.auth.backends.ModelBackend 만 삽입했는데

    에러는 그대로 발생하네요..


    그리고 authenticate()는 signin( 로그인)함수에 사용하는데

    아직 회원가입으로 등록되어 있는 회원정보가 없어서 정확히 작동되는지는 모르겠는데

    로그인은 별 문제가 없는거 같습니다.



    0
  • 우르르응
    148
    2019-05-26 14:42:13

    흠.. 에러 내용으로 검색을 해보셔야 할 것 같네요 ㅜ

    혹시 회원가입 후 바로 로그인을 처리하는 구조는 아닌가요?

    0
  • raek
    2k
    2019-05-26 14:49:31

    우르르응

    답변 정말 감사합니다.

    에러로는

    2019-05-26 02:27:37,076 DEBUG member_manager.views testa13@gmail.com  12341234q

    2019-05-26 02:27:37,089 DEBUG member_manager.views 'AnonymousUser' object has no attribute '_meta'


    이렇게 똑같이 뜨는데


    django 에서 쓰고있는 models.py 를 추가로 본문에 올렸습니다.

    여기서는 문제가 없을까요?

    참고로 https://wayhome25.github.io/django/2017/05/18/django-auth/

    이 링크를 참고했습니다. 그런데 구조가 좀 다르게됬어요..

    0
  • 우르르응
    148
    2019-05-26 15:25:40
    설정(settings.py) 또는 Django에 내장된 모듈을 잘못 사용하는 과정에서 생긴 에러같아요.

    찾아보니, 커스텀 인증 관련된 에러 같은데요.
    공식문서에서 올바른 사용법을 한 번 보시는게 에러를 찾을 수 있지 않을까 생각되네요.
    https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#a-full-example

    settings.py도 올려주시겠어요?
    0
  • raek
    2k
    2019-05-26 15:41:07 작성 2019-05-26 15:42:25 수정됨

    우르르응

    이렇게 까지 봐주셔서 정말 감사합니다..

    참고로 이메일하고 비번은 노출될 수 없어 예시로 했습니다.

    settings.py 입니다.

    """
    Django settings for vip_ml_server project.
    
    Generated by 'django-admin startproject' using Django 2.0.5.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/2.0/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/2.0/ref/settings/
    """
    
    import os
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'zw!gxzm8mhx4vey4gn@e&$x(6u3&=(9=2p^^c^5@&@(^xphixs'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    ALLOWED_HOSTS = []
    
    AUTH_USER_MODEL = "member_manager.User"
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
        'rest_framework_swagger',
        'predict_app',
        'member_manager',
        'corsheaders'
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',     # add
        'django.middleware.common.CommonMiddleware', # add
        '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',
    ]
    
    CORS_ORIGIN_ALLOW_ALL = True
    
    CORS_ORIGIN_WHITELIST = [
        "http://localhost:30",
        "http://localhost:100"
    ]
    
    ROOT_URLCONF = 'vip_ml_server.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    TEMPLATE_DIRS = (
        os.path.join(BASE_DIR, 'templates'),
    )
    
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.AllowAny',
        ]
    }
    
    WSGI_APPLICATION = 'vip_ml_server.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
            'LOCATION': './tmp/django_cache',
            'TIMEOUT': None,
        }
    }
    
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': '%(asctime)s %(levelname)s %(name)s %(message)s'
            },
        },
        'handlers': {
            'default': {
                'level':'DEBUG',
                'class':'logging.handlers.RotatingFileHandler',
                'filename': 'vip_ml_server.log',
                'maxBytes': 1024*1024*5, # 5MB
                'backupCount': 5,
                'formatter':'standard',
            },
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
                'formatter': 'standard',
            }
        },
        'loggers': {
            '': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': True
            },
        }
    }
    
    LOGIN_REDIRECT_URL = 'main/index'   # 추가
    
    # Password validation
    # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    AUTHENTICATION_BACKENDS = [ # 추가
        'django.contrib.auth.backends.ModelBackend', # Django가 관리하는 AUTH
    ]
    
    
    # Internationalization
    # https://docs.djangoproject.com/en/2.0/topics/i18n/
    
    LANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = True
    
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/2.0/howto/static-files/
    
    STATIC_URL = '/static/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'static')
    MEDIA_URL = ''
    STATIC_ROOT = ''
    STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )
    
    
    
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_USE_TLS = True
    EMAIL_PORT = 587
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_HOST_USER = 'example123@gmail.com'
    EMAIL_HOST_PASSWORD = 'exmaple123!'
    #SERVER_EMAIL = 'example123@gmail.com'
    DEFAULT_FROM_MAIL = EMAIL_HOST_USER



    0
  • 우르르응
    148
    2019-05-26 16:09:35

    http://corpus.hubwiz.com/2/angularjs/31773354.html

    Django Rest Framework에서 login()호출에 대한 문제를 다루고 있네요.

    이렇게 한 번 해보시겠어요?

    login(request._request, request.user)

    저도 장고를 잘 몰라서.. 집단지성으로 풀어나가봐요 ㅜㅜ ㅋㅋ

    0
  • raek
    2k
    2019-05-26 16:15:42

    우르르응

    답변 정말 감사합니다.

    views.py의

    def signup(request):

    부분에서

    login(request, new_user, backend='django.contrib.auth.backends.ModelBackend')

    login(request._request, request.user)

    이렇게 바꾸라는 말씀이신가요?


    0
  • 우르르응
    148
    2019-05-26 16:16:59 작성 2019-05-26 16:21:45 수정됨
    아 해당 부분은 로그인과 관련된 부분 같네요.. ㅋㅋ

    흠.. 검색해보니 class Meta() 같은 것들도 있던데..
    저는 잘 모르겠네요 ㅜㅜ
    장고 고수분이 해결해주시길 기다려봅니다..
    뭔가 공식문서에서 커스텀 인증과 관련된 부분에 해답이 있을거 같아요;;
    0
  • raek
    2k
    2019-05-26 16:27:09 작성 2019-05-26 16:27:22 수정됨

    우르르응

    기존에 views.py에 있는 

    코드중에 

    login(request, new_user, backend='django.contrib.auth.backends.ModelBackend') 을 

    login(request._request, request.user) 으로 바꾸니


    'WSGIRequest' object has no attribute '_request' 에러가 뜨네요

    이건 _request가 signup 함수 안에 들어 있지 않기 때문에 일어나는건가요?

    구글에 검색해보는데.. _request가 어디 있어야 하는 건지.. 잘 모르겠네요..


    @csrf_exempt
    def signup(request):
        try:
            body = json.loads(request.body)
            email = body['id']
            passwd = body['passwd']
            logger.debug('{} {}'.format(email, passwd))
            
            new_user = UserManager.create_user(email, passwd)
            #login(request, new_user, backend='django.contrib.auth.backends.ModelBackend')
            login(request._request, request.user)
            return JsonResponse({'result': 'success'})
        except Exception as e:
            logger.debug(e)
            return JsonResponse({'result': 'fail'})



    0
  • 우르르응
    148
    2019-05-26 16:41:06
    login(request._request, request.user)
    이건 아닌가봐요. 혼란만 드렸네요..
    0
  • raek
    2k
    2019-05-26 16:43:23

    우르르응

    아닙니다..

    정말 친절한 답변 감사드립니다.


    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.