2. 화면 구성 - (8) 회원가입 화면
[1] 개요
1. URL
- HOST/register
2. 구성
- 아이디 입력창 (현재 아이디 중복 체크 기능X)
- 비밀번호 입력창
- 비밀번호확인 입력창 (현재 비밀번호 확인 기능X)
- 이름 입력창
- 생년월일 입력창
- 성별 선택 라디오버튼
- 이메일 입력창 (현재 이메일 중복 체크 기능X)
- 주소 찾기 버튼 및 상세주소 입력창
- 휴대폰번호 입력창 (현재 휴대폰번호 중복 체크 기능X)
- 프로필 사진 파일 선택 버튼
- 일반회원/점주 선택 라디오버튼
- 이상 필수입력 사항
- 회원가입 버튼
- 점주 선택 시
- 사업자등록번호 입력창(필수)
- 식당이름 입력창(필수)
- 점주이름 입력창(필수)
- 주소 찾기 버튼 및 상세주소 입력창(필수)
- 음식점정보 입력창
- 음식점 연락처 입력창
- 영업시간 입력창
- 재료준비시간 입력창
- 음식점사진 파일 선택 버튼
- 업종 선택 콤보박스
[2] CODE
1. HTML
/templates/register.html
<section class="p-5">
<div class="m-5" style="position:absolute; left:50%; transform:translateX(-50%); width:35%;">
<header class="container p-3" style="text-align:center; width:100%;">
<h3 style="white-space:nowrap;">회원가입</h3>
</header>
<form name="regist" action="registerimpl" method="post" id="register_box" enctype="multipart/form-data" style="text-align:left;">
{% csrf_token %}
<div class="input-box">
<input id="custid" type="text" name="custid" placeholder="아이디" autocomplete="off" required>
<label for="custid">아이디</label>
</div>
<div class="input-box">
<input id="custpw" type="password" name="custpw" placeholder="비밀번호" onchange="check_pw()" required>
<label for="custpw">비밀번호</label>
</div>
<div class="input-box">
<input id="custpwcheck" type="password" name="pwcheck" placeholder="비밀번호확인" onchange="check_pw()" required>
<label for="custpwcheck">비밀번호확인</label>
</div>
<div class="input-box">
<input id="custname" type="text" name="custname" placeholder="이름" autocomplete="off" required>
<label for="custname">이름</label>
</div>
<div class="input-box">
<input id="custbday" type="date" name="birth" placeholder="생년월일" autocomplete="off" required>
<label for="custbday">생년월일</label>
</div>
<div>
<div class="box-radio-input">
<input id="man" type="radio" name="gender" value="남" style="width:15px; height:15px;" required>
<span>남자</span>
<input id="woman" type="radio" name="gender" value="여" style="width:15px; height:15px;" required>
<span>여자</span>
</div>
</div>
<div class="input-box">
<input id="custemail" type="text" name="custemail" placeholder="이메일" autocomplete="off" required>
<label for="custemail">email</label>
</div>
<div class="input-box">
<div class="formfield m-1" id="custaddr">
<input type="text" id="sample4_postcode" placeholder="우편번호" required>
<input type="button" onclick="sample4_execDaumPostcode()" value="주소 찾기" style="border:1px solid grey; border-radius:3px;">
<br>
<input type="text" id="sample4_roadAddress" name="address1" placeholder="도로명주소" style="width:40%" required>
<input type="text" id="sample4_jibunAddress" placeholder="지번주소" style="width:40%" required>
<br>
<span id="guide" style="color:#999;display:none"></span>
<span>상세주소</span>
<input type="text" id="sample4_detailAddress" name="address2" placeholder="상세주소" style="width:30%" required>
<input type="text" id="sample4_extraAddress" placeholder="참고항목" style="width:30%" required>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
//본 예제에서는 도로명 주소 표기 방식에 대한 법령에 따라, 내려오는 데이터를 조합하여 올바른 주소를 구성하는 방법을 설명합니다.
function sample4_execDaumPostcode() {
new daum.Postcode({
oncomplete: function(data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 도로명 주소의 노출 규칙에 따라 주소를 표시한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
var roadAddr = data.roadAddress; // 도로명 주소 변수
var extraRoadAddr = ''; // 참고 항목 변수
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if(data.buildingName !== '' && data.apartment === 'Y'){
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if(extraRoadAddr !== ''){
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('sample4_postcode').value = data.zonecode;
document.getElementById("sample4_roadAddress").value = roadAddr;
document.getElementById("sample4_jibunAddress").value = data.jibunAddress;
// 참고항목 문자열이 있을 경우 해당 필드에 넣는다.
if(roadAddr !== ''){
document.getElementById("sample4_extraAddress").value = extraRoadAddr;
} else {
document.getElementById("sample4_extraAddress").value = '';
}
var guideTextBox = document.getElementById("guide");
// 사용자가 '선택 안함'을 클릭한 경우, 예상 주소라는 표시를 해준다.
if(data.autoRoadAddress) {
var expRoadAddr = data.autoRoadAddress + extraRoadAddr;
guideTextBox.innerHTML = '(예상 도로명 주소 : ' + expRoadAddr + ')';
guideTextBox.style.display = 'block';
} else if(data.autoJibunAddress) {
var expJibunAddr = data.autoJibunAddress;
guideTextBox.innerHTML = '(예상 지번 주소 : ' + expJibunAddr + ')';
guideTextBox.style.display = 'block';
} else {
guideTextBox.innerHTML = '';
guideTextBox.style.display = 'none';
}
}
}).open();
}
</script>
</div>
<div class="input-box">
<input id="custphone" type="tel" name="custphone" placeholder="휴대폰번호" autocomplete="off" required>
<label for="custphone">휴대폰번호</label>
</div>
<div class="input-box" style="padding-top:8px;">
<span style="font-size:15px;">프로필사진
<input type="file" id="custimg" name="custimg" accept="image/*"></span>
</div>
<div>
<div class="box-radio-input">
<input id="cust" type="radio" name="host_flag" value="0" onclick="div_OnOff(this.value,'con');" style="width:15px; height:15px;" required>
<span>일반회원</span>
<input id="ceo" type="radio" name="host_flag" value="1" onclick="div_OnOff(this.value,'con');" style="width:15px; height:15px;" required>
<span>점주</span>
<script>
function div_OnOff(v,id){
// 라디오 버튼 value 값 조건 비교
if(v == "1"){
document.getElementById(id).style.display = ""; // 보여줌
list = document.getElementsByClassName('con_input');
for (var i = 0; i < list.length; i++){
list[i].setAttribute("required", "");// 점주용 필드값 required 로 변경
}
}else{
document.getElementById(id).style.display = "none"; // 숨김
list = document.getElementsByClassName('con_input');
for (var i = 0; i < list.length; i++){
list[i].removeAttribute("required");// 점주용 필드값 required 제거
}
}
}
</script>
<div id="con" style="display:none">
점주용 필드
<div class="input-box">
<input id="reg_num" class="con_input" type="text" name="reg_num" placeholder="식당이름" autocomplete="off" minlength="10" maxlength="10">
<label for="reg_num">사업자등록번호</label>
</div>
<div class="input-box">
<input id="rest_name" class="con_input" type="text" name="rest_name" placeholder="식당이름" autocomplete="off">
<label for="rest_name">식당이름</label>
</div>
<div class="input-box">
<input id="host_name" class="con_input" type="text" name="host_name" placeholder="점주이름" autocomplete="off">
<label for="host_name">점주이름</label>
</div>
<div class="input-box">
<div class="formfield m-1" id="hostaddr">
<input type="text" id="sample4_hpostcode" class="con_input" placeholder="우편번호">
<input type="button" onclick="sample4_hexecDaumPostcode()" value="주소 찾기" style="border:1px solid grey; border-radius:3px;">
<br>
<input type="text" id="sample4_hroadAddress" class="con_input" name="address3" placeholder="도로명주소" style="width:40%">
<input type="text" id="sample4_hjibunAddress" class="con_input" placeholder="지번주소" style="width:40%">
<br>
<span id="hguide" style="color:#999;display:none"></span>
<span>상세주소</span>
<input type="text" id="sample4_hdetailAddress" class="con_input" name="address4" placeholder="상세주소" style="width:30%">
<input type="text" id="sample4_hextraAddress" class="con_input" placeholder="참고항목" style="width:30%">
</div>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
//본 예제에서는 도로명 주소 표기 방식에 대한 법령에 따라, 내려오는 데이터를 조합하여 올바른 주소를 구성하는 방법을 설명합니다.
function sample4_hexecDaumPostcode() {
new daum.Postcode({
oncomplete: function(data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 도로명 주소의 노출 규칙에 따라 주소를 표시한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
var roadAddr = data.roadAddress; // 도로명 주소 변수
var extraRoadAddr = ''; // 참고 항목 변수
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if(data.buildingName !== '' && data.apartment === 'Y'){
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if(extraRoadAddr !== ''){
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('sample4_hpostcode').value = data.zonecode;
document.getElementById("sample4_hroadAddress").value = roadAddr;
document.getElementById("sample4_hjibunAddress").value = data.jibunAddress;
// 참고항목 문자열이 있을 경우 해당 필드에 넣는다.
if(roadAddr !== ''){
document.getElementById("sample4_hextraAddress").value = extraRoadAddr;
} else {
document.getElementById("sample4_hextraAddress").value = '';
}
var hguideTextBox = document.getElementById("hguide");
// 사용자가 '선택 안함'을 클릭한 경우, 예상 주소라는 표시를 해준다.
if(data.autoRoadAddress) {
var expRoadAddr = data.autoRoadAddress + extraRoadAddr;
hguideTextBox.innerHTML = '(예상 도로명 주소 : ' + expRoadAddr + ')';
hguideTextBox.style.display = 'block';
} else if(data.autoJibunAddress) {
var expJibunAddr = data.autoJibunAddress;
hguideTextBox.innerHTML = '(예상 지번 주소 : ' + expJibunAddr + ')';
hguideTextBox.style.display = 'block';
} else {
hguideTextBox.innerHTML = '';
hguideTextBox.style.display = 'none';
}
}
}).open();
}
</script>
</div>
<div class="input-box">
<input id="restindex" type="text" name="restindex" placeholder="음식점정보" autocomplete="off">
<label for="restindex">음식점정보</label>
</div>
<div class="input-box">
<input id="hostphone" type="text" name="hostphone" placeholder="음식점연락처" autocomplete="off">
<label for="hostphone">음식점연락처</label>
</div>
<div class="input-box">
<input id="openhour" type="text" name="openhour" placeholder="영업시간" autocomplete="off">
<label for="openhour">영업시간</label>
</div>
<div class="input-box">
<input id="breakhour" type="text" name="breakhour" placeholder="휴식시간" autocomplete="off">
<label for="breakhour">재료준비시간</label>
</div>
<div class="input-box" style="padding-top:8px;">
<span>음식점사진
<input type="file" id="restimg" name="restimg" accept="image/* "></span>
</div>
<div class="input-box">
<span>업종을선택하세요</span>
<select id="cate_id" name="cate_id" required>
<option value="">선택</option>
<option value="10">한식</option>
<option value="20">분식</option>
<option value="30">디저트</option>
<option value="40">일식</option>
<option value="50">치킨</option>
<option value="60">피자</option>
<option value="70">아시안</option>
<option value="80">양식</option>
<option value="90">중식</option>
<option value="100">패스트푸드</option>
</select>
</div>
</div>
</div>
</div>
<br>
<div class="btnfield" style="text-align:center">
<input type="submit" value="회원가입" style="width:80%">
</div>
<br>
<br>
<br>
</div>
</form>
</div>
</section>
2. CSS
- /static/css/styles.css
3. JavaScript
- HTML 에 포함
- 주소 검색 API
- 일반회원/점주 라디오버튼 클릭에 따른 점주용 필드 화면 출력 결정
4. Application
1) register( )
- 회원가입 화면으로 이동
2) registerimpl( )
- /registerimpl 을 요청하여 회원가입 화면에서 입력된 정보를 POST 방식으로 받아서 처리
- 점주로 가입하는 경우(host_flag==1), 해당 정보 별도 테이블에 저장
- 회원가입 완료되면, id 정보를 request.session에 저장하여, 자동으로 로그인 되도록 구현
- 현재 회원가입 버튼 클릭 후, 입력된 정보에 따라서 오류가 나는 경우, 예외처리가 되어있지 않음
@request_mapping("")
class MyView(View):
@request_mapping("/register", method="get")
def register(self, request):
return render(request, 'register.html');
@request_mapping("/registerimpl", method="post")
def registerimpl(self, request):
host_flag = int(request.POST['host_flag']);
id = request.POST['custid'];
pwd = request.POST['custpw'];
name = request.POST['custname'];
birth = request.POST['birth'];
gender = request.POST['gender'];
email = request.POST['custemail'];
address1 = request.POST['address1'];
address2 = request.POST['address2'];
phone = request.POST['custphone'];
imgname = '';
if 'custimg' in request.FILES:
img = request.FILES['custimg'];
imgname = img._name;
f = open('%s/%s' % (UPLOAD_DIR, imgname), 'wb')
for chunk in img.chunks():
f.write(chunk);
f.close();
profile = Cust(id=id, pwd=pwd, name=name, birth=birth, gender=gender, email=email,
address=address1 + address2,
phone=phone, host_flag=host_flag, custimg=imgname);
profile.save();
if host_flag==1:
reg_num = request.POST['reg_num'];
rest_name = request.POST['rest_name'];
host_name = request.POST['host_name'];
address3 = request.POST['address3'];
address4 = request.POST['address4'];
restindex = request.POST['restindex'];
hostphone = request.POST['hostphone'];
openhour = request.POST['openhour'];
breakhour = request.POST['breakhour'];
cate_id = request.POST['cate_id']
imgname2 = '';
if 'restimg' in request.FILES:
img = request.FILES['restimg'];
imgname2 = img._name;
f = open('%s/%s' % (UPLOAD_DIR, imgname2), 'wb')
for chunk in img.chunks():
f.write(chunk);
f.close();
restprf = Rest(cust=profile, reg_num=reg_num, rest_name=rest_name, host_name=host_name, address=address3 + address4,
restindex=restindex, phone=hostphone, openhour=openhour, breakhour=breakhour, cate_id=cate_id, restimg=imgname2);
restprf.save();
# 회원가입 완료 시, 자동 로그인
request.session['sessionid'] = profile.id
request.session['sessionname'] = profile.name
request.session['sessionimg'] = profile.custimg
return redirect('/')
- 끝 -