需求:完成设计一个登陆的接口,要求返回一个json格式的响应。
分析:在视图层完成登陆请求的用户名和密码的数据库数据校验,然后返回对应的json格式结果。
结果可能性:
第一:用户名重名,这是个bug需要返回一个状态,数据库中存在两个重名的用户
第二:用户名不存在,在数据库中查询不到
第三:密码错误
第四:都正确
定义json的格式:"reason": "数据库中存在同名的用户","result": [],"error_code": 2000
"reason": "用户名不存在","result": [],"error_code": 2001
"reason": "密码错误","result": [],"error_code": 2002
"reason": "数据库服务错误","result": [],"error_code": 2003
{
"reason": "登陆成功",
"result": {
username:请求的用户名
password:登陆成功
},
"error_code": 0 / * 登陆成功* /
}
第一步:先获取到请求中的用户名和密码数据
def get_userinfo(self,method_obj): #与前端页面进行交互的,同样可以设定默认值,如果前端没有对应的属性时,则取默认值,如果有值则取前端所获取到属性所对应的值 get_username=method_obj.get("username","wangwu") #如果携带的参数不是username的话,则默认值是wangwu get_password=method_obj.get('password') return {"password":get_password,"username":get_username}
第二步:获取数据库中数据,此处以django自带的sqlite的数据库为实例:
SQLite数据库是专门针对嵌入式开发的数据库软件,占用资源非常少(仅需几百K内存即可),处理速度快,而且可以直接使用C语言编程,同时也可以配合C#、PHP、Java等其他语言。
特点:
1.占用资源非常少(仅仅需要几百k即可)
2.处理速度快
3.小型数据库灵活方便
4.可以直接使用C语言编程
5.大量的内置对象库
该类型的数据库后缀:一般设定都是db或者sqlite后缀的,当然也存对应的IDE:sqliteadmin、sqliteSpy等
SQLite3数据库使用 使用SQLite3需要安装,如果自己机器之前配置过SDK的话,那么就可以直接使用sqlite了,因为SDK中包含sqlite的应用程序。 如果没有的话,则可以通过官网进行下载:https://www.sqlite.org/download.html
下载好后,进行解压缩,然后将其目录路径配置到环境变量path中。
直接在terminal内输入sqlite即可进入SQLite3数据库软件,通过手动输入SQL命令行完成数据库的创建。
SQLite3创建数据库
在terminal输入 sqlite3 mydb.db或者.open mydb.db都可以完成一个的数据库的创建,同样如果mydb.db不存在的话使用.open则会新建一个,如果存在的话则表示打开一个数据库。
如果想退出数据库,则可以使用命令.quit(简写为.q)或者.exit(简写为.e)退出数据库。
查看数据库文件信息命令(注意命令前带字符'.'):
sqlite>.database
列出数据库中的表名(.tables)
sqlite> .tables
输出所有SQL命令(.dump)
“.dump”命令可以用来查看表结构,也可以查看构成该表的所有SQL命令:
sqlite> .dump
以sql语句的形式列出表内容:
sqlite>.dump table_name
查看所有表的创建语句:
sqlite>.schema
查看指定表的创建语句:
sqlite>.schema table_name
设置每一列的显示宽度:
sqlite>.width width_value#例如:设置宽度为2sqlite>.width 2
具体对表结构的增、删、改、查以及数据的增、删、改、查等操作与常用的sql语句相同,这里就不过多说明了。
针对第二个步的实现,已创建了数据库my.db,且创建了表userinfo,存在一条记录用户名:zhangsan,密码:123456
在模型层中创建一个模块连接sqlite数据库,并完成数据的读取操作,具体代码如下:
#-*- coding:utf-8 -*-##-------------------------------------------------------------------------#ProjectName: Python2020#FileName: Conn_Sqlite.py#Author: mutou#Date: 2020/7/12 14:57#Description:#--------------------------------------------------------------------------#该文件完成sqlite数据库中的数据读取操作#任何一个数据库操作其主要都是基于链接对象的创建import sqlite3from InterfaceProgram.settings import BASE_DIRclass ConnSqlite(object): def __init__(self): self.conn=sqlite3.connect(BASE_DIR+"/Login/Modle/my.db") self.cursor=self.conn.cursor() #读取数据 def read_data(self,str_sql): self.cursor.execute(str_sql) get_reuslt=self.cursor.fetchall() return get_reusltif __name__ == '__main__': print(BASE_DIR+"Login/Modle/my.db") conn=ConnSqlite() str_sql="select password from userinfo where username='%s'"%'zhangsan' print(conn.read_data(str_sql))
第三步:完成从请求中获取的数据与数据库中数据进行对比,具体业务逻辑实现如下:
def get_database(self,username): conn = ConnSqlite() str_sql = "select password from userinfo where username='%s'" % username return conn.read_data(str_sql)def compare_data(self,method_obj): get_page_info=self.get_userinfo(method_obj) get_database_info=self.get_database(get_page_info["username"]) print("获取的页面信息:",get_page_info) return_reuslt={"reason": [],"result": [],"error_code":[]} if len(get_database_info)>1: return_reuslt["reason"]="数据库中存在同名的用户" return_reuslt["error_code"]=2000 #return {"reason": "数据库中存在同名的用户","result": get_page_info,"error_code": 2000} elif len(get_database_info)==0: return_reuslt["reason"] = "用户名不存在" return_reuslt["error_code"] = 2001 #return {"reason":"用户名不存在","result": get_page_info,"error_code": 2001} elif get_database_info[0][0]!=get_page_info["password"]: return_reuslt["reason"] = "密码错误" return_reuslt["error_code"] = 2002 #return {"reason": "密码错误","result": get_page_info,"error_code": 2002} else: return_reuslt["reason"] = "登陆成功" return_reuslt["error_code"] = 0 return_reuslt["result"]=get_page_info #return { "reason": "登陆成功","result":get_page_info,"error_code": 0 } return return_reuslt
首先第一个方法用于进行连接数据库,第二个方法实现比较,并设定返回指定内容的格式数据。
第四步:通过指定的请求方法将结果响应给客户端,例如,声明get和post方法
def get(self,request): #return HttpResponse(self.get_userinfo(request.GET)) return HttpResponse(json.dumps(self.compare_data(request.GET),ensure_ascii=False))def post(self,request): return HttpResponse(json.dumps(self.compare_data(request.POST),ensure_ascii=False))
那么以上所有的代码就构成了视图层的整个业务逻辑处理实现,将上面的所有方法声明在一个类中即可
第五步:完成urls路由映射操作
from django.contrib import adminfrom django.urls import pathfrom Login.View.Login_Check_Action import LoginCheckActionurlpatterns = [ path('admin/', admin.site.urls), path("loginAction",LoginCheckAction.as_view()),]
注意:如果是post请求,在请求过程中出现403forbidden的话,则需要修改django中的设置,如下图:
因为CSRF 表示django全局发送post请求均需要字符串验证
功能:防止跨站请求伪造的功能
工作原理:客户端访问服务器端,在服务器端正常返回给客户端数据的时候,而外返回给客户端一段字符串,等到客户端下次访问服务器端时,服务器端会到客户端查找先前返回的字符串,如果找到则继续,找不到就拒绝。
如果就是不想注释的话,可以通过修改header,在views打印cookie可以得到csrftoken
def index(request): print("cookie",request.COOKIES) #cookie { # 'csrftoken': 'AB9v1MGTbdpSGg3FaGCIiUxrKVR8zKSqgdGFDn5E0ADsJ2ST7N2zgW6KboQ8G31x', # 'sessionid': 'eexw5p38vky9qo38nf372dz5lj1br6xf' # } #cookie 是浏览器给的, return HttpResponse("index")