iT邦幫忙

2021 iThome 鐵人賽

DAY 6
0
Modern Web

30天肝出購物網站系列 第 6

Day06:06 - User服務(1) - 後端 - 註冊、登入、Python正則表達式

Hi,Сәлам,我是Charlie!

在Day05當中我們完成了Django的基本架構跟資料庫,今天我們要來做註冊跟登入囉。今天的註冊跟登入是基本程序,Day07中是前端的基本註冊跟登入,而在Day08當中我們會完成JWT -- 令牌的部分。

================================◉‿◉=================================

首先在users裡面建立urls.py,並在裡面新增url patterns:

from django.conf.urls import url
from . import views

urlpatterns = [
	url(r'^$',views.users)
]

並到專案主資料夾的urls import url跟include,把users的url傳入:

from django.conf.urls.static import static
from django.conf.urls import url,include

urlpatterns = [
    path('admin/', admin.site.urls),
    url('user',include('users.urls'))
]

然後到settings裡面加上:

APPEND_SPLASH = False

接著到users的views.py,新增一個視圖,並且返回一個JsonRespnose:

from django.shortcuts import render
from django.http import JsonResponse

def users(request):
	return JsonResponse({"status":200,"message":"Hello World"})

在這裡我們要使用postman來測試API,首先到官網下載postman:
https://www.postman.com/downloads/

在安裝完postman之後,新增一個request,在url的地方打入:
http://localhost:8000/user

Send完之後,看到Json回應就是成功了:
https://ithelp.ithome.com.tw/upload/images/20210920/20141666l7T3H2eh0L.png

但這樣子的話會發現,每次都要寫status = 200,status_code非常的分散,所以我們從tools裡面新增一個R.py,建立status常量跟Result class:

from django.http import JsonResponse

# status code: 200 OK
STATUS_OK = 200

# status code 201 : created
CREATED = 201

# status code 401 : Unauthorized
UNAUTHORIZED = 401

# status code: 400 Bad Request
BAD_REQUEST = 400

# status code: 405 method not allowed
METHOD_NOT_ALLOWED = 405

# status code: 500 Internal Server Error
INTERNAL_SERVER_ERROR = 500

class R:
	@staticmethod
	def ok(data = None):
		if data is None:
			return JsonResponse({"code":STATUS_OK})
		return JsonResponse({"code":STATUS_OK,"data":data})

	@staticmethod
	def created(data = None):
		if data is None:
			return JsonResponse({"code":CREATED})
		return JsonResponse({"code":CREATED,"data":data})

	@staticmethod
	def unauthorized(data = None):
		if data is None:
			return JsonResponse({"code":UNAUTHORIZED})
		return JsonResponse({"code":UNAUTHORIZED,"data":data})

	@staticmethod
	def badRequest(data = None):
		if data is None:
			return JsonResponse({"code":BAD_REQUEST})
		return JsonResponse({"code":BAD_REQUEST,"data":data})

	@staticmethod
	def methodNotAllowed(data = None):
		if data is None:
			return JsonResponse({"code":METHOD_NOT_ALLOWED})
		return JsonResponse({"code":METHOD_NOT_ALLOWED,"data":data})

	@staticmethod
	def internalServerError(data = None):
		if data is None:
			return JsonResponse({"code":INTERNAL_SERVER_ERROR})
		return JsonResponse({"code":INTERNAL_SERVER_ERROR,"data":data})


if __name__ == "__main__":
	print(R.internalServerError("server is busy"))

接著我們將views裡面的Hello World改寫:

def users(request):
	return R.ok("Hello World")

就可以看到正常的Json Response了:
https://ithelp.ithome.com.tw/upload/images/20210920/20141666zqmTEuJFew.png

再來是註冊的部分,註冊是使用POST,並且需要GET Json的資料,所以這邊要先判斷方法是否為POST,如果是的話就解析內容。
而我們需要model來解析JSON跟取得資料,所以先建立一個User Model:

import json

class UserModel:
	def __init__(self,username = "",password = "",password1 = "",phone = "",email = "",address = ""):
		self.username = username
		self.password = password
		self.password1 = password1
		self.phone = phone
		self.email = email
		self.address = address

	def fromJson(self,data):
		jsondata = json.loads(data)
		self.username = jsondata["username"] if "username" in jsondata else None
		self.password = jsondata["password"] if "password" in jsondata else None
		self.password1 = jsondata["password1"] if "password1" in jsondata else None
		self.phone = jsondata["phone"] if "phone" in jsondata else None
		self.email = jsondata["email"] if "email" in jsondata else None
		self.address = jsondata["address"] if "address" in jsondata else None

	def __str__(self):
		return "UserModel[username=%s,password=%s,password1=%s,phone=%s,email=%s,address=%s" % (self.username,self.password,self.password1,self.phone,self.email,self.address)

接著到users的地方建立新的程式碼,印出UserModel試試看:

def users(request):
	if request.method == "POST":
		res = request.body
		user = UserModel()
		user.fromJson(res)
		print(user)
		return R.ok("Hello World")
	else:
		return R.methodNotAllowed("Method Not Allowed")

接著到postman, 方法選擇POST,另外加上body:
https://ithelp.ithome.com.tw/upload/images/20210920/20141666WQrPBecVlU.png

send之後就可以看到Hello World。

接著我們要開始做register的驗證,這裡要使用re模組:

import re

接著使用正則表達式:

if not re.match("^[A-Za-z0-9]*$",user.username):
	return R.badRequest("username contains invalid character")
if not re.match('^(\w|\.|\_|\-)+[@](\w|\_|\-|\.)+[.]\w{2,3}$',user.email):
	return R.badRequest("email is not correct")

第一個的是除了大小寫字母跟數字以外的都不匹配,第二個則是匹配email的格式。

接下來是密碼,密碼不可小於6位數,phone則是不可小於10位並且只能有數字:

if not re.match("^[0-9]*$",user.phone) or len(user.phone) != 10:
	return R.badRequest("phone is not correct")
if len(user.password < 6):
	return R.badRequest("password length is not correct")
return R.created("user created")

還有password跟password1必須一致:

if user.password != user.password1:
	return R.badRequest("password verify failed")

這些都做完之後,代表驗證正確,要開始註冊了。

首先是密碼,密碼必須加鹽,這裡我們使用hashlib的md5來加密:

import hashlib

md5 = hashlib.md5()
passwordString = user.password + user.username
md5.update(passwordString.encode())
pwd = md5.hexdigest()

接著我們create User Model:

u = User.objects.create(
		name = user.username,
		password = pwd,
		phone = user.phone,
		address = user.address
	)
u.save()

測試:
https://ithelp.ithome.com.tw/upload/images/20210920/20141666mY38dfQqwD.png
https://ithelp.ithome.com.tw/upload/images/20210920/20141666oW07xp3DvQ.png

再來是登入,登入的話先另外起一個app:

$ python manage.py startapp login

並在INSTALLED_APPS裡面加入login,還有在urls裡面加入login:

# keyboardmarket\urls.py

url('login',include('login.urls'))

# login\urls.py

from django.conf.urls import url
from . import views

urlpatterns = [
	url(r'^$',views.login)
]

接著先在login中判斷傳回的json data,判斷是否有這個用戶:

if request.method == "POST":
	res = request.body
	user = UserModel()
	user.fromJson(res)
	fuser = User.objects.filter(name = user.username)
	if len(fuser) == 0:
		return R.badRequest("User does not exist")
else:
	return R.methodNotAllowed("method not allowed")

接著要判斷密碼是否相同,這裡也是使用hashlib比對:

password = fuser[0].password
md5 = hashlib.md5()
passwordString = user.password + user.username
md5.update(passwordString.encode())
pwd = md5.hexdigest()
if pwd != password:
	return R.badRequest("password incorrect")
return R.ok("Authorize success")

接著用POSTMAN打試試看:
https://ithelp.ithome.com.tw/upload/images/20210920/201416661GMbcDZASj.png

================================◉‿◉=================================

Day06結束了! 在這邊我們先完成了註冊跟登入的基本程序,在Day07當中會完成前端的註冊跟登入,然後在Day08時,我們會真正完成登入跟註冊:利用JWT令牌判別。See ya next day!


上一篇
Day05: 05 - Django架構規劃、資料庫規劃、商品資料準備
下一篇
Day07:07 - User服務(2) - 前端 - 註冊、登入、JS正則表達式
系列文
30天肝出購物網站30

尚未有邦友留言

立即登入留言