使用django和django-rest-framework开发RESTful后端程序(1)用户系统

使用django和django-rest-framework开发RESTful后端程序(1)用户系统

0.简介

以后的一系列教程将会制作一个简单的卖东西的网站,希望大家都能有所收获。

还需要强调的是,本系列教程主要使用的IDE是Pycharm : PyCharm: the Python IDE for Professional Developers by JetBrains;python的版本是3.7;django的版本是2.1.4;django rest framework版本是3.9.0,大家不要用错了版本,以免造成奇怪的bug。

在上一个章节我们学会了如何创建一个django项目和应用,并开发一个django rest framework风格的接口,这章节我们将基于django构建一个用户系统。


1.使用mysql数据库

注:此小节不是必须部分,可酌情跳过。

django本身是有简单的sqlite数据库支持的,如果仅仅进行一些简易的开发,是不需要更改数据库的设定的。但是如果你打算把数据库更改为myslq或其他数据库,就需要做一些简单的更改了。

首先我们把数据库设置为mysql。打开settings.py文件,找到DATABASES设置:

这里可以看到django的默认设置是sqlite3。sqlite3是一个微型数据库,自己玩是可以的,但是如果进行生产开发,仍然建议使用其他的数据库,比如mysql。

django的官方文档里有支持数据库的设置方法:Databases | Django documentation | Django,我们参照文档中的设置来进行自己的设置——

文档:

首先我们在根目录创建一个conf文件,然后将数据库配置放入其中:

数据库配置的格式参照文档写:

[client]
database = demo
user = root
password = xxxxxxx
default-character-set = utf8

这里使用了database=demo,使用前需进入mysql命令行使用create database demo; 来创建此数据库

注:此处使用的是本地的mysql数据库,更复杂的例如远程数据库,读写分离等请参考文档。mysql数据库的安装和设置此处亦不做赘述,请自行寻找教程或跳过此小节。

随后我们更改setting文件,让其支持mysql数据库并使用我们的配置文件:

DATABASES = {
    'default': {
        # mysql引擎
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {
            # 配置文件的路径
            'read_default_file': 'conf/database.cnf',
        },
    }
}

然后我们打开命令行,使用命令初始化django的数据库:

$ python manage.py migrate

随后django会在数据库中生成若干张自带的表:

这样数据库的初始化就完成了。

如果我们进入mysql数据库,使用use demo;和show tables;命令,会发现demo数据库中多了若干张表,这些就是django自带的几张默认表,其中就包含了用户相关的若干表。


2.视图部分

在上一章的学习中,我们学会了如何创建一个应用并将其添加至settings中,现在我们依葫芦画瓢再创建一个应用:

$ python manage.py startapp hera

然后我们添加路由文件,把此路由文件的路径添加到总路由文件中,然后把app添加到settings文件中。

(注:上述操作在上一章节有详细教程,此处不做细述)

一个完整的用户系统,一般包括注册,登录和登出这三个接口,首先我们把大体的架子搭出来,然后再慢慢实现。

from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from django.contrib.auth.models import User

class UserViewSet(GenericViewSet):
    # 注册,post方法
    @action(methods=["POST"], detail=False)
    def register(self, request, *args, **kwargs):
        pass

    # 登录,post方法
    @action(methods=["POST"], detail=False)
    def login(self, request, *args, **kwargs):
        pass

    # 登出,get方法(这里是为了图方便,其实应该使用put/post方法)
    @action(methods=["GET"], detail=False)
    def logout(self, request, *args, **kwargs):
        pass

简单介绍一下@action装饰器,这个装饰器的主要作用是将被装饰的函数注册到路由上,省去了一个个手动添加的麻烦,后面常见的有两个参数:methods是一个list,里面是被允许使用的http请求方法的大写英文字符串;detail则是是否在路由中加入详细数值。

在import的第四行,我们导入了django自带的User表,这里是使用了django自己的用户系统,好处就是不需要改东西,坏处就是diy不方便,在后续的教程我们会教大家如何建立自己的用户系统。

然后我们把此视图注册到hera的urls上:

from rest_framework.routers import DefaultRouter
from app_ex.hera import views

router = DefaultRouter()
router.register(r'user',views.UserViewSet,base_name="user")
urlpatterns = router.urls

注册函数:

class UserViewSet(GenericViewSet):

    # 注册,post方法
    @action(methods=["POST"], detail=False)
    def register(self, request, *args, **kwargs):
        username = request.data.get("username")
        password = request.data.get("password")
        # username和password不能缺失 否则无法注册 返回http code 400
        if not username or not password:
            return Response(status=400,
                            data={"msg": "need username or password"})
        # username已存在 返回http code 409
        if User.objects.filter(username=username):
            return Response(status=409, data={"msg": "username existed"})
        # 使用user的create_user方法创建用户 注意:尽量用此方法创建用户
        user = User.objects.create_user(
            username=username,
            password=password)
        return Response({"msg": "success","user_id":user.id})

其中request.data获取的是前端发送的json格式的数据,如果是表单需要用request.POST,如果是get方法,则需要用request.GET。获取username和password之后要判断是否为空,然后判断用户名是否存在,再进行用户创建。

登录函数:

我们首先在import里添加几个需要的函数

from django.contrib.auth import authenticate, login
from django.http.response import HttpResponseRedirect

然后构建此函数:

    # 登录,post方法
    @action(methods=["POST"], detail=False)
    def login(self, request, *args, **kwargs):
        username = request.data.get("username")
        password = request.data.get("password")
        if not username or not password:
            return Response(status=400,
                            data={"msg": "need username or password"})
        # django官方的密码验证 验证密码务必使用此函数
        user = authenticate(request, username=username, password=password)
        if user is not None:
            # django的官方用户登录函数 登录用户使用此函数
            login(request, user)
            # 跳转到info页面
            return HttpResponseRedirect("/user/info")
        else:
            # 密码或账号错误 返回403错误
            return Response(status=403,
                            data={"msg": "username or password error"})

其中authenticate函数和login函数都是django本身的函数,在验证密码和登入用户的时候需要用到这两个函数,因为这两个函数内部比较复杂,就不做解释和复写了,大家用就好了。

而登录成功之后跳转到的用户信息界面,我们等会也会进行构建。

登出函数:

登出函数需要用到django的logout函数,在import里添加此函数

from django.contrib.auth import logout

然后直接logout即可

    # 登出,get方法(这里是为了图方便,其实应该使用put/post方法)
    @action(methods=["GET"], detail=False)
    def logout(self, request, *args, **kwargs):
        logout(request)
        # 重定向至home
        return HttpResponseRedirect("/hello/world")

info函数:

用户信息部分涉及到建表的操作,我们暂时不做那么复杂的工作,仅返回user的id:

    @action(methods=["GET"], detail=True)
    def info(self, request, *args, **kwargs):
        # django中常用的获取当前用户的方法
        user = request.user
        # 目前暂时没有做info的详细 可以只返回一个id
        return Response({"user_id":user.id})

以上就是一个极度简单的django rest framework用户系统常见接口的构建,同时我也已经将代码上传至github,地址:

huisezhiyin/Demogithub.com图标

此教程是task_hera分支,上面的地址已经进行了切换。

编辑于 2019-01-11

文章被以下专栏收录