DRF 商城项目-用户相关业务逻辑梳理

1.用户登录

自定义登录验证逻辑

本项目中用户登录既可以是用户名,也可以是手机号,所以需要重写登录验证逻辑

class CustomBackend(ModelBackend):
    """
    自定义用户验证
    """
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username)|Q(mobile=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None
登录API
# 配置jwt路由
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    # jwt的认证接口
    path('login/', obtain_jwt_token),
]
登录逻辑

利用jwt生成token实现登录,返回生成的token。

2.用户注册

用户注册基于 手机注册
发送验证码基于 榛子云网
相关链接:

  1. 榛子云网址
  2. 示例
  3. 接口文档

验证码逻辑

验证码API
from users.views import SmsViewSet
from rest_framework.routers import DefaultRouter

# Create a router and register our viewsets with it.
router = DefaultRouter()

#配置手机短信验证码url
router.register(r'codes', SmsViewSet, base_name="codes")
验证码序列化组件

选取序列化方式的时候以为不是全部的字段都需要用上, 因此不需用到 ModelSerializer
mobile 字段相关验证:

  1. 是否注册
  2. 是否合法
  3. 频率限制
import re
import datetime

from django.contrib.auth import get_user_model
from rest_framework import serializers

from MxShop.settings import REGEX_MOBILE
from .models import VerifyCode

User = get_user_model()


# 为啥不用serializers.ModelSerializer,因为短信验证码模型有code和mobile两个字段
# 而注册的时候只有手机号,用ModelSerializer就会导致验证失败
class SmsSerializer(serializers.Serializer):
    """
    短信验证码验证
    """
    mobile = serializers.CharField(max_length=11)

    def validated_mobile(self, mobile):
        """
        验证手机号码,函数名规则为:validated_字段名()
        :return:
        """
        # 验证手机号是否已经注册
        if User.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("用户已经存在")

        # 验证手机号是否合法
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号码非法")


        # 验证手机号是否为一分钟前验证过了(防止恶意注册)
        one_min_ago = datetime.datetime.now() - datetime.timedelta(minutes=1)
        if VerifyCode.objects.filter(add_time__gt=one_min_ago, mobile=mobile).count():
            raise serializers.ValidationError("距离上一次发送未超过60s")

        return mobile
验证码视图逻辑处理

视图主要处理 验证码生成发送相关逻辑

具体的榛子云网接口对接处理详情官网查阅

from random import choice

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.shortcuts import render
from rest_framework.mixins import CreateModelMixin
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status

from .serializer import SmsSerializer
from MxShop.settings import APIKEY, AppId, AppSecret
from utils.zhenzi import ZhenziSmsClient
from .models import VerifyCode


class SmsViewSet(CreateModelMixin, viewsets.GenericViewSet):
    """
    发送短信验证码
    """
    serializer_class = SmsSerializer

    def random_generate_code(self):
        """
        随机生成四位数验证啊
        :return:
        """
        seeds = '1234567890'
        random_str = []
        for i in range(4):
            random_str.append(choice(seeds))
        code = ''.join(random_str)
        return code


    def create(self, request, *args, **kwargs):
        """
        重写create方法
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        serializer = self.get_serializer(data=request.data)
        # raise_exception=True代表验证失败报异常
        serializer.is_valid(raise_exception=True)
        # 取出手机号(验证成功才会执行)
        mobile = serializer.validated_data['mobile']
        # # 随机生成四位数验证码
        code = self.random_generate_code()
        zhen_zi = ZhenziSmsClient("https://sms_developer.zhenzikj.com/", AppId, AppSecret)
        send_status = zhen_zi.send(message="您的验证码是: {}。如非本人操作,请忽略本短信".format(code), number=mobile)
        send_status = eval(send_status)
        if send_status['code'] != 0:
            # 发送失败
            return Response({
                'mobile': send_status['data']
            }, status=status.HTTP_400_BAD_REQUEST )
        else:
            # 发送成功
            # 只有在发送成功时才能保存数据
            verify = VerifyCode(mobile=mobile, code=code)
            verify.save()

            return Response({
                'mobile': send_status['data']
            }, status=status.HTTP_201_CREATED)
榛子云验证码工具
# -*- coding: utf-8 -*-
__author__ = 'kevin'
__date__ = '2019/6/24 11:10'
import urllib.request
import urllib.parse
import ssl


class ZhenziSmsClient(object):
    def __init__(self, apiUrl, appId, appSecret):
        self.apiUrl = apiUrl
        self.appId = appId
        self.appSecret = appSecret

    def send(self, number, message, messageId='', ):
        data = {
            'appId': self.appId,
            'appSecret': self.appSecret,
            'number': number,
            'messageId': messageId,
            'message': message
        }

        data = urllib.parse.urlencode(data).encode('utf-8')
        ssl._create_default_https_context = ssl._create_unverified_context
        req = urllib.request.Request(self.apiUrl + '/sms/send.do', data=data)
        res_data = urllib.request.urlopen(req)
        res = res_data.read()
        res = res.decode('utf-8')
        return res
榛子云相关配置
# 榛子云网配置
AppId = 我的应用的AppId 
AppSecret = '我的应用的AppSecret '

注册逻辑

用户注册API
# 配置用户注册url
router.register(r'register', UserViewSet, base_name="users")
注册序列化组件

选取序列化方式的时候以为是全部的字段都需要用上, 所以要用到 ModelSerializer
前端传过来的所有的数据都在, initial_data 字典里面
验证个别字段方法名必须是:validate_ + 字段名
code字段相关验证:

  1. 是否存在
  2. 是否过期
  3. 是否和数据库中相同

为啥使用filter方法查询验证码,而不用get方法呢?

  1. 如果使用 get 方式需要处理两个异常, 分别是查找到多个信息的情况以及查询到0信息的情况的异常
  2. 但是使用 filter 方式查到多个就以列表方式返回, 如果查询不到数据就会返回空值, 各方面都很方便

字段属性说明:

  1. write_only - 只读字段包含在API输出中,但在创建或更新操作期间不应包含在输入中。 任何错误包含在序列化程序输入中的’read_only’字段都将被忽略。将此属性设置为True可确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。
  2. required - 必填
  3. max_length - 最大长度
  4. min_length - 最小长度
  5. error_messages - 错误类型映射提示(blank-空字段提示 required-必填字段提示 max_length-超长度提示 min_length-过短提示)
  6. style - 更改输入标签显示类型
  7. validators - 可以指明一些默认的约束类
  8. help_text - 帮助提示信息
  9. label - 显示名字
  10. allow_blank - 将此参数设置为True将意味着序列化输出的默认值为null,但并不意味着输入反序列化的默认值
class UserRegisterSerializer(serializers.ModelSerializer):
    """
    用户注册
    """
    # write_only=True: code设置这个参数,防止返回时序列化报错->返回时该属性已经被删除
    code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, error_messages={
        'max_length': '验证码格式错误',
        'min_length': '验证码格式错误',
        'required': '请输入验证码',
        'blank': '请输入验证码'
    }, help_text='手机验证码')

    # validators 可以指明一些默认的约束类, 此处的 UniqueValidator 表示唯一约束限制不能重名
    username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")])

    # style 可以设置为密文状态
    password = serializers.CharField(
        style={'input_type': 'password'}, help_text="密码", label="密码", write_only=True,
    )

    # 用户表中的 password 是需要加密后再保存的, 次数需要重写一次 create 方法
    # 当然也可以不这样做, 这里的操作利用 django 的信号来处理, 详情见 signals.py
    # def create(self, validated_data):
    #     user = super(UserRegSerializer, self).create(validated_data=validated_data)
    #     user.set_password(validated_data["password"])
    #     user.save()
    #     return user

    # 对验证码的验证处理
    # validate_ + 字段对个别字段进行单一处理
    def validated_code(self, code):

        # 如果使用 get 方式需要处理两个异常, 分别是查找到多个信息的情况以及查询到0信息的情况的异常
        # 但是使用 filter 方式查到多个就以列表方式返回, 如果查询不到数据就会返回空值, 各方面都很方便
        # try:
        #     verify_records = VerifyCode.objects.get(mobile=self.initial_data["username"], code=code)
        # except VerifyCode.DoesNotExist as e:
        #     pass
        # except VerifyCode.MultipleObjectsReturned as e:
        #     pass

        # 前端传过来的所有的数据都在, initial_data 字典里面, 如果是验证通过的数据则保存在 validated_data 字典中
        all_records = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by("-add_time")
        if all_records:
            # 时间倒叙排序后的的第一条就是最新的一条
            last_record = all_records[0]

            # 五分钟前的时间
            five_mintes_ago = datetime.datetime.now() - datetime.timedelta(minutes=5)

            # 验证码过期
            if five_mintes_ago > last_record.add_time:
                raise serializers.ValidationError('验证码过期')

            # 验证码错误
            if code != last_record.code:
                raise serializers.ValidationError('验证码错误')
            # return code  # 没必要保存验证码记录, 仅仅是用作验证
        else:
            # 手机号没有
            raise serializers.ValidationError('验证码错误')

    # 对所有的字段进行限制
    def validate(self, attrs):
        # 重命名一下
        attrs['mobile'] = attrs['username']
        # 删除无用字段
        del attrs['code']
        return attrs

    class Meta:
        model = User
        # username字段是系统中的字段
        fields = ("username", "code", "mobile")
注册视图逻辑处理

视图主要处理 :

  1. 注册时用户的创建
  2. 重写 create 函数来完成注册后自动登录并跳转到主页面(原因:默认的create方法只能实现用户创建无法实现其他附加)
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler

class UserViewSet(CreateModelMixin, viewsets.GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserRegisterSerializer
默认的create方法
class CreateModelMixin(object):
    """
    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 {}

如果想实现自动登录, 首先本质就是加入用户登录的状态, 即 token 的生成和保存

本次项目使用的是 JWT 作为 token 方案, 因此 需要考究在 JWT 的源码中 token 如何生成

密码加密

方法一 在Serializer类中重写create方法:

# apps/users/serializer.y

# 用户表中的 password 是需要加密后再保存的, 故需要重写一次 create 方法
# 当然也可以不这样做, 这里的操作利用 django 的信号来处理, 详情见 signals.py
  def create(self, validated_data):
      user = super(UserRegisterSerializer, self).create(validated_data=validated_data)
      user.set_password(validated_data["password"])
      user.save()
      return user

方法二 利用django的信号量机制:
名称解释:

  1. created - 是否新建
  2. post_save - Django中的model对象保存后,自动触发
  3. sender - 指定User模型(指定要执行的模型)
  4. instance - 表示保存对象, 在这里是被保存的 user 对象
  5. set_password - 密码加密方法
# apps/users/signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model

User = get_user_model()

@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        password = instance.password
        instance.set_password(password)
        instance.save()
# apps/users/apps.py

from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'
    # 后台管理应用显示
    verbose_name = '用户'

    def ready(self):
        import users.signals

JWT流程分析

JWT API
# 配置jwt路由
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    # jwt的认证接口
    path('login/', obtain_jwt_token),
]
类视图
class RefreshJSONWebToken(JSONWebTokenAPIView):
    """
    API View that returns a refreshed token (with new expiration) based on
    existing token

    If 'orig_iat' field (original issued-at-time) is found, will first check
    if it's within expiration window, then copy it to the new token
    """
    serializer_class = RefreshJSONWebTokenSerializer


obtain_jwt_token = ObtainJSONWebToken.as_view()
refresh_jwt_token = RefreshJSONWebToken.as_view()
verify_jwt_token = VerifyJSONWebToken.as_view()
class ObtainJSONWebToken(JSONWebTokenAPIView):
    """
    API View that receives a POST with a user's username and password.

    Returns a JSON Web Token that can be used for authenticated requests.
    """
    serializer_class = JSONWebTokenSerializer
序列化组件实现token生成
class JSONWebTokenSerializer(Serializer):
    """
    Serializer class used to validate a username and password.

    'username' is identified by the custom UserModel.USERNAME_FIELD.

    Returns a JSON Web Token that can be used to authenticate later calls.
    """
    def __init__(self, *args, **kwargs):
        """
        Dynamically add the USERNAME_FIELD to self.fields.
        """
        super(JSONWebTokenSerializer, self).__init__(*args, **kwargs)

        self.fields[self.username_field] = serializers.CharField()
        self.fields['password'] = PasswordField(write_only=True)

    @property
    def username_field(self):
        return get_username_field()

    def validate(self, attrs):
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }

        if all(credentials.values()):
            user = authenticate(**credentials)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                payload = jwt_payload_handler(user)

                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)

具体的源码逻辑,根据路由自行查找。

具体的token生成
if user:
      if not user.is_active:
          msg = _('User account is disabled.')
          raise serializers.ValidationError(msg)

      payload = jwt_payload_handler(user)

      return {
          'token': jwt_encode_handler(payload),
          'user': user
      }

生成token用到的方法:

  1. jwt_payload_handler
  2. jwt_encode_handler
具体实现
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler

class UserViewSet(CreateModelMixin, viewsets.GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserRegisterSerializer

    # 重写 create 函数来完成注册后自动登录功能
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = self.perform_create(serializer)

        re_dict = serializer.data
        payload = jwt_payload_handler(user)
        # 通过token 的添加只能用此方法
        re_dict["token"] = jwt_encode_handler(payload)
        # 自定义一个字段加入进去
        re_dict["name"] = user.name if user.name else user.username


        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

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

3.用户退出

由于jwt不是保存在服务器端,而是保存在客服端,所以退出不需要再写一个 logout 接口 。只需要前端进行cookie的清空然后跳转到登录页面或主页面都可以,我这里是跳转到登录页面。

<script>
  import { mapGetters } from 'vuex';
  export default {
    computed: {
      ...mapGetters({
        userInfo:'userInfo'
      })
    },
    methods: {
      loginOut(){
        cookie.delCookie('token');
        cookie.delCookie('name');
        //重新触发store
        //更新store数据
        this.$store.dispatch('setInfo');
        //跳转到登录
        this.$router.push({name: 'login'})
      },
    }
  }
</script>

4.个人中心

个人资料的显示和修改

当我去获取用户详情信息的时候,我们就会发现我们不知道用户的id,这时候我们就可以通过重写get_object(控制retieve/delete)的方法返回当前用户。

def get_object(self):
    """
    由于用户id未知,想要通过id获取用户详细信息不行
    :return: 返回当前用户对象
    """
    return self.request.user

当我们获取当前用户的时候,就出现另外一个问题,用户必须是登录的状态才可以,但是注册的时候用户又没有登录。所以我就可以通过动态的加载权限,具体如下:

  1. 用户注册时,无权限,所有人都可以
  2. 用户的获取、用户的修改时,IsAuthenticate权限
from rest_framework.permissions import IsAuthenticated

def get_permissions(self):
    """
    动态加载权限
    """
    # 只有是viewsets才有action
    if self.action == "retrieve":
        return [IsAuthenticated()]
    elif self.action == "create":
        return []
    # 其它方法必须也要有权限
    return []

加上登录验证

# JSONWebTokenAuthentication --> JWT登录验证
authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication)

此时我们测试接口就会发现只显示两个字段的值,这是注册的序列化组件的值,所以我们还要实现动态加载序列化组件。

# users/serizalizer.py
class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        # username字段是系统中的字段
        fields = ("name", "gender", "birthday", "email", "mobile")

# users/views.py
def get_serializer_class(self):
  """
   注册和用户同用一个视图,不同serializer
   :return: 序列化组件
   """
   if self.action == "retrieve":
       return UserDetailSerializer
   elif self.action == "create":
       return UserRegisterSerializer
   # 其它方法必须也要有权限
   return UserDetailSerializer

修改个人信息,继承UpdateModelMixin即可

class UserViewSet(CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):

参考资料:
DRF 商城项目 - 用户( 登录, 注册,登出,个人中心 ) 逻辑梳理
相关链接:
Django中的信号及其用法
signals官方文档
内置信号文档

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在前面的文章中,我们已经介绍了如何使用DRF编写RESTful API和如何进行身份验证。在本文中,我们将继续探讨如何使用DRF实现前后端分离。具体来说,我们将使用Vue.js作为前端框架,并使用axios实现与后端API的通信。 1. 安装Vue.js和axios 首先,我们需要安装Vue.js和axios。我们可以使用npm来进行安装: ``` npm install vue npm install axios ``` 2. 创建Vue.js应用程序 我们可以使用Vue CLI来创建Vue.js应用程序。在命令行中输入以下命令: ``` npm install -g vue-cli vue init webpack myapp ``` 其中,myapp是应用程序的名称。在创建应用程序时,我们需要回答一些问题,例如选择使用哪种模板、是否安装vue-router等。我们可以根据自己的需要进行选择。 3. 编写Vue.js组件 接下来,我们需要编写Vue.js组件来与后端API进行通信。在本例中,我们将创建一个名为“TaskList”的组件,用于显示任务列表并提供添加任务的功能。 在src/components目录下创建TaskList.vue文件,并编写以下代码: ```html <template> <div> <h2>Tasks</h2> <ul> <li v-for="task in tasks" :key="task.id"> {{ task.title }} </li> </ul> <input type="text" v-model="title"> <button @click="addTask">Add Task</button> </div> </template> <script> import axios from 'axios'; export default { data() { return { tasks: [], title: '' }; }, created() { this.getTasks(); }, methods: { getTasks() { axios.get('http://localhost:8000/api/tasks/') .then(response => { this.tasks = response.data; }); }, addTask() { axios.post('http://localhost:8000/api/tasks/', { title: this.title }) .then(response => { this.tasks.push(response.data); this.title = ''; }); } } }; </script> ``` 在这个组件中,我们首先导入axios库,然后定义了一个名为“TaskList”的组件。在data函数中,我们定义了两个变量:tasks用于存储任务列表,title用于存储新任务的标题。在created函数中,我们调用getTasks函数来获取任务列表。在methods对象中,我们定义了两个方法:getTasks用于获取任务列表,addTask用于添加新任务。在getTasks函数中,我们使用axios库进行HTTP GET请求,并在响应中将tasks变量更新为获取的数据。在addTask函数中,我们使用axios库进行HTTP POST请求,并在响应中将新任务添加到tasks变量中。 4. 引入组件 最后,我们需要将TaskList组件引入Vue.js应用程序。在App.vue文件中,我们可以编写以下代码: ```html <template> <div id="app"> <TaskList /> </div> </template> <script> import TaskList from './components/TaskList.vue'; export default { name: 'App', components: { TaskList } }; </script> ``` 在这个文件中,我们首先导入TaskList组件,然后在components对象中注册它。最后,在模板中调用它。 5. 运行应用程序 现在,我们可以使用以下命令启动Vue.js应用程序: ``` npm run dev ``` 在浏览器中访问http://localhost:8080,您将看到一个任务列表和一个添加任务的表单。当您添加新任务时,它将被添加到列表中并保存到后端API中。 总结 在本文中,我们介绍了如何使用Vue.js和axios实现与DRF后端API的通信,并创建了一个名为“TaskList”的组件来显示任务列表和添加新任务。这是一个简单的示例,但您可以使用类似的方法来创建更复杂的应用程序。 ### 回答2: Django前后端分离实践之DRF--09主要是关于Django Rest Framework(DRF)在前后端分离开发中的实践。DRF是基于Django的一款强大的Web API框架,它提供了一系列的功能和工具,使得开发者能够轻松地构建和管理API。 在这个实践中,首先我们需要将前端和后端进行分离。前端可以使用任何JavaScript框架,如Vue.js或React来构建用户界面,并通过HTTP请求与后端进行通信。而后端则是使用Django和DRF来构建API。 DRF提供了一些类和方法,能够帮助我们更方便地开发API。例如,通过使用DRF的序列化器,我们可以轻松地将数据库模型转化为JSON格式。此外,DRF还提供了视图和路由器等组件,使得开发者能够更快速地构建API视图和URL路由。 在实践过程中,我们还可以使用DRF的认证和权限系统来保护API的安全性。DRF支持各种认证方式,如基于Token的认证和基于Session的认证。同时,我们可以基于DRF的权限系统来限制用户对API的访问权限,确保只有经过授权的用户才能进行操作。 此外,DRF还提供了一些其他的功能,如过滤器、分页和搜索等,使得我们能够更精细地控制API的行为和展示方式。 总之,Django前后端分离实践之DRF--09主要介绍了如何使用DRF来构建前后端分离的应用。通过DRF提供的强大功能和工具,我们可以更便捷地开发高效、安全的API,并提供给前端进行交互和展示。 ### 回答3: DRF即Django Rest Framework是一种用于构建Web API的强大工具,它使得前后端分离开发成为可能。在实践中,Django的后端提供数据的存储和处理功能,而前端使用DRF来访问API并展示数据。 首先,我们需要在Django中安装和配置DRF。可以通过在settings.py中添加'django_rest_framework'到INSTALLED_APPS列表中来安装DRF。然后,在urls.py中配置API的路由。 在Django中,我们可以使用数据库模型来定义数据模型,在使用DRF时,我们需要创建一个序列化器类来定义返回给前端的数据结构。序列化器由字段组成,可以定义字段的类型、验证规则等。我们可以使用DRF提供的ModelSerializer来快速创建序列化器类,它会自动根据模型的字段来生成对应的序列化器字段。 在视图中,我们可以使用基于类的视图来处理API请求。DRF提供了一系列的视图类,如APIView、ViewSet等,可以根据实际需求选择使用。视图类中的方法对应不同的HTTP操作,如GET、POST、PUT、DELETE等。 DRF还提供了身份验证、权限控制、过滤、排序等功能,可以根据项目的需求进行配置。 使用DRF的前后端分离实践中,前端可以通过发送GET、POST、PUT等请求来获取和操作数据。后端则负责处理请求并返回响应。前端可以通过AJAX、fetch等方法来发送请求并获取数据,然后使用HTML、CSS和JavaScript来展示数据。 在前后端分离开发中,前端和后端可以并行开发,各自独立测试,并且可以轻松地修改API而不会影响到前端界面。这种开发模式使得团队协作更加高效,同时也方便进行项目的维护和扩展。 总而言之,Django前后端分离实践之DRF可以极大地提升开发效率和团队协作能力。通过合理配置和使用DRF提供的功能,可以实现强大的API开发,使得前后端分离成为一种高效和可行的开发方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值