前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.寻光集后台管理系统-用户管理(注册视图)

6.寻光集后台管理系统-用户管理(注册视图)

作者头像
zx钟
发布2022-12-02 15:46:31
7510
发布2022-12-02 15:46:31
举报
文章被收录于专栏:测试游记

django中视图本质上就是个函数,接受用户传入的请求,返回对应的响应。

在视图中处理业务逻辑。django约定将视图放在views.py的文件中。这个文件应放在项目或者应用目录中。

函数视图

基于函数的视图

代码语言:javascript
复制
def some_view(request):
  dosometing
  return HttpResponse(html)

特点:

  1. 逻辑清晰好理解
  2. 复用性较差

类视图

基于类的视图,换了一种写法,不能替代函数视图,有一些优势:

  • 用特定的方法去管理http方法(get post)
  • 使用面向对象的技术,可以将代码分解成可重用的组件

所以后续大部分会采用类视图的方式编写代码

注册视图

注册需要前端发起一个携带需要注册的账号密码的post请求

这种常规的增删改查视图DRF已经封装好了,直接进行继承即可

代码语言:javascript
复制
from rest_framework import generics

class UserRegisterView(generics.CreateAPIView):
    serializer_class = UserRegisterSerializer

只需要两行就完成了注册类视图的编写

看一下CreateAPIView类具体干了什么,可以点击进行跳转

代码语言:javascript
复制
class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):
    """
    Concrete view for creating a model instance.
    """
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

它就是接收了响应,然后把响应数据传递给create函数

代码语言:javascript
复制
class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

分步查看一下它都干了什么

1. 获取请求数据

代码语言:javascript
复制
serializer = self.get_serializer(data=request.data)

查看其中的get_serializer

代码语言:javascript
复制
def get_serializer(self, *args, **kwargs):
    kwargs['context'] = self.get_serializer_context()
    return self.serializer_class(*args, **kwargs)

def get_serializer_context(self):
    return {
        'request': self.request,
        'format': self.format_kwarg,
        'view': self
    }

这里的serializer_class就是指定我们编写的序列化器UserRegisterSerializer

就是这一步把前端传递过来的json对象,处理成了一个python对象

2. 数据校验

代码语言:javascript
复制
serializer.is_valid(raise_exception=True)

从上一步可以看出,这里的serializer就是UserRegisterSerializer的实例化对象

UserRegisterSerializer又是继承的serializers.ModelSerializer

所以这个is_valid的路径为rest_framework.serializers.BaseSerializer.is_valid

代码语言:javascript
复制
def is_valid(self, raise_exception=False):
    assert hasattr(self, 'initial_data'), (
        'Cannot call `.is_valid()` as no `data=` keyword argument was '
        'passed when instantiating the serializer instance.'
    )

    if not hasattr(self, '_validated_data'):
        try:
            self._validated_data = self.run_validation(self.initial_data)
        except ValidationError as exc:
            self._validated_data = {}
            self._errors = exc.detail
        else:
            self._errors = {}

    if self._errors and raise_exception:
        raise ValidationError(self.errors)

    return not bool(self._errors)

暂时了解它的功能就是去判断数据是否符合我们的规定即可

3. 保存数据

代码语言:javascript
复制
self.perform_create(serializer)

def perform_create(self, serializer):
    serializer.save()

同上,save方法调用的是rest_framework.serializers.BaseSerializer.save

代码语言:javascript
复制
def save(self, **kwargs):
    assert hasattr(self, '_errors'), (
        'You must call `.is_valid()` before calling `.save()`.'
    )

    assert not self.errors, (
        'You cannot call `.save()` on a serializer with invalid data.'
    )

    # Guard against incorrect use of `serializer.save(commit=False)`
    assert 'commit' not in kwargs, (
        "'commit' is not a valid keyword argument to the 'save()' method. "
        "If you need to access data before committing to the database then "
        "inspect 'serializer.validated_data' instead. "
        "You can also pass additional keyword arguments to 'save()' if you "
        "need to set extra attributes on the saved model instance. "
        "For example: 'serializer.save(owner=request.user)'.'"
    )

    assert not hasattr(self, '_data'), (
        "You cannot call `.save()` after accessing `serializer.data`."
        "If you need to access data before committing to the database then "
        "inspect 'serializer.validated_data' instead. "
    )

    validated_data = {**self.validated_data, **kwargs}

    if self.instance is not None:
        self.instance = self.update(self.instance, validated_data)
        assert self.instance is not None, (
            '`update()` did not return an object instance.'
        )
    else:
        self.instance = self.create(validated_data)
        assert self.instance is not None, (
            '`create()` did not return an object instance.'
        )

    return self.instance

这个save方法兼容了更新新建两个操作

如果self.instance非空,则是更新。否则为新建

新建的时候调用的create方法

代码语言:javascript
复制
def create(self, validated_data):
    raise NotImplementedError('`create()` must be implemented.')

这个创建是个抽象方法,所以需要我们去实现它

我们在users.serializers.UserRegisterSerializer.create中实现了它

代码语言:javascript
复制
def create(self, validated_data):
    validated_data.pop('password_confirm')
    return User.objects.create_user(**validated_data)

至此就完成了注册

小结

虽然分析了一堆,但是实际上代码只有

代码语言:javascript
复制
from rest_framework import generics
from users.serializers import UserRegisterSerializer


class UserRegisterView(generics.CreateAPIView):
    serializer_class = UserRegisterSerializer

路由

路由的作用和路由器类似,当一个用户请求django站点的一个页面时,是路由系统通过对url的路径部分进行匹配,一旦匹配成功就导入并执行对应的视图来返回响应。

  1. 当一个请求来到时,django首先到项目中查找根路由模式,在其中查找路由匹配规则。
  2. 根路由模块,就是项目文件目录下的urls.py文件。这个文件中定义了一个变量urlpatterns。它应该是一个django.urls.path(),或者是django.urls.re_path()对象的列表。
  3. django按顺序运行每个url模式,并在与请求的url匹配的第一个模式停止。
  4. 一旦其中一个url模式匹配,django将导入并调用给定的视图。
  5. 如果没有匹配,或者在此过程中引发任何异常,django调用错误视图。

注册路由

根路由

在根路由backend/LightSeeking/urls.py中添加

代码语言:javascript
复制
path('users/', include('users.urls')),

表示前端可以使用http://IP:端口/users/xx来访问users.urls里面的路由

代码语言:javascript
复制
from django.contrib import admin
from django.urls import path, include

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

include可以接收一个表示导入路由模块的字符串,也可以接收一个路由模式列表。

代码语言:javascript
复制
include(module, namespace=None)
include(pattern_list)
include((pattern_list, app_namespace), namespace=None)

应用路由

在users文件夹中新建一个urls.py文件来管理应用的路由

写上注册的路由

代码语言:javascript
复制
from django.urls import path
from . import views

urlpatterns = [
    path('register/', views.UserRegisterView.as_view(), name='register'),
]

测试

至此完成了序列化器+视图+路由,那么我们就可以发起注册请求了

打开postman来进行测试

请求地址:http://127.0.0.1:8000/users/register/

请求方式:POST

请求数据:

代码语言:javascript
复制
{
  "username": "zhongxin",
  "password": "123456",
  "password_confirm": "123456",
  "email": "490336534@qq.com",
  "mobile": "13000000000",
  "name": "测试游记"
}

发送请求

查看响应

代码语言:javascript
复制
{
    "id": ,
    "username": "zhongxin",
    "email": "490336534@qq.com",
    "mobile": "13000000000",
    "name": "测试游记"
}

查看数据库

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试游记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数视图
  • 类视图
  • 注册视图
    • 1. 获取请求数据
      • 2. 数据校验
        • 3. 保存数据
          • 小结
          • 路由
          • 注册路由
            • 根路由
              • 应用路由
              • 测试
              相关产品与服务
              文件存储
              文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档