drf 視圖組件

来源:https://www.cnblogs.com/elijah-li/archive/2022/04/03/16094982.html
-Advertisement-
Play Games

內容概要 request 對象和 response 對象 GenericAPIView 介紹 基於 GenericAPIView 的 5個視圖擴展類 GenericAPIView 的9個視圖子類 視圖集 ModelViewSet 的使用 ViewSetMixin 源碼分析 內容詳細 request ...


內容概要

  • request 對象和 response 對象
  • GenericAPIView 介紹
  • 基於 GenericAPIView 的 5個視圖擴展類
  • GenericAPIView 的9個視圖子類
  • 視圖集
  • ModelViewSet 的使用 ViewSetMixin 源碼分析

內容詳細

request 對象和 response 對象

請求之 request 對象

我們已經知道,drf 對原生的 request 請求數據對象做過封裝處理,原生 request 對象被保存在_request 中,通過 __getattr__【點攔截】魔法方法可以獲取 原生 request 對象所有方法和屬性,並且 drf 的 request 可以通過 request.data 取出包括 json 格式數據在內的所有編碼格式,使得數據處理更加方便。

導入模塊 Request

from rest_framework.request import Request

request 對象需要記憶:

  • __getattr__
  • request.data
  • request.query_parmas

request.query_parmas 源碼:接受原生 request 對象的GET 請求的數據,也就是過濾參數

@property
def query_params(self):
    """
    More semantically correct name for request.GET.
    """
    return self._request.GET

限制 request 能接收的數據格式

局部配置:

在視圖層的視圖類中配置,限制 request 對象只能處理json格式數據,只針對當前視圖類有效

from rest_framework.parsers import JSONParser,FormParser,MultiPartParser

class PublishView(APIView):
    # 局部使用,只針對當前視圖類有效,只想處理json格式
    parser_classes = [JSONParser]
    
    def get(self, request):
		pass

全局配置:

在項目文件夾下的 settings.py文件中配置

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ],
}

解析順序:
視圖層類中的配置 > 項目文件夾下 settings.py 文件配置 > drf 原有的預設配置

drf的預設配置:from rest_framework import settings

image

響應之 response 對象

from rest_framework.response import Response

形參:

data=None,    # 字元串,字典,列表--》給http響應body體中內容-->response對象中取出處理
status=None,  # 響應狀態碼:1xx,2xx,3xx,預設是200
from rest_framework.status import HTTP_201_CREATED
Response(ser.data,status=HTTP_201_CREATED)

headers=None,      # 響應頭 字典

---瞭解---
template_name=None,  # 模板名字(不用),用瀏覽器訪問時,可以改
exception=False,    # 異常處理
content_type=None   # 響應編碼格式

設置響應的數據格式:

局部設置:

from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookDetailView(APIView):
    renderer_classes = [JSONRenderer,]

全局設置:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (  # 預設響應渲染類
        'rest_framework.renderers.JSONRenderer',  # json渲染器
        'rest_framework.renderers.BrowsableAPIRenderer',  # 瀏覽API渲染器
    )
}

GenericAPIView 介紹

GenericAPIView 繼承的是 APIView

前面我們已經知道 APIView 對原生 request 對象進行了處理,新的request對象多了 .data 屬性,並且有三大認證和全局異常處理。

APIView還擁有限制請求和響應數據的屬性 renderer_classes,parser_classes

那麼,GenericAPIView 就是在 APIView 的基礎上,多了更多屬性和方法

from rest_framework.generics import GenericAPIView

更多屬性和方法可以查看 GenericAPIView 源碼

屬性:

class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None
    lookup_field = 'pk'
    lookup_url_kwarg = None
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

方法:

image

優先記憶:

屬性

  • queryset = None : 獲取模型類對象
  • serializer_class = None : 獲取序列化類的屬性
  • lookup_field = 'pk' : 獲取單個對象時需要用到改屬性

方法:

  • get_queryset :獲取模型類對象 queryset
  • get_object : 獲取單個模型類對象
  • get_serializer :獲取序列化類執行並返回一個序列化後的對象
  • get_serializer_class : 獲取序列化類
get_queryset
    def get_queryset(self):
        # 斷言 self.queryset 不為空,否則報錯後面信息,說明 queryset 屬性必須定義
        assert self.queryset is not None, (
            "'%s' should either include a `queryset` attribute, "
            "or override the `get_queryset()` method."
            % self.__class__.__name__
        )
        # 獲取 queryset 屬性並放回
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
        return queryset

get_serializer
    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs.setdefault('context', self.get_serializer_context())
        return serializer_class(*args, **kwargs)

get_serializer_class
    def get_serializer_class(self):
        assert self.serializer_class is not None, (
            "'%s' should either include a `serializer_class` attribute, "
            "or override the `get_serializer_class()` method."
            % self.__class__.__name__
        )
        return self.serializer_class
    
get_object
    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        assert lookup_url_kwarg in self.kwargs, (
            'Expected view %s to be called with a URL keyword argument '
            'named "%s". Fix your URL conf, or set the `.lookup_field` '
            'attribute on the view correctly.' %
            (self.__class__.__name__, lookup_url_kwarg)
        )
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)
        self.check_object_permissions(self.request, obj)
        return obj

基於 GenericAPIView 的 5個視圖擴展類

不是視圖類,沒有繼承APIView,需要配合GenericAPIView 使用,這五個類中提供了查找、新增、修改刪除模型類數據的方法,在GenericAPIView類的五個介面中可以直接調用

  • CreateModelMixin
  • ListModelMixin
  • DestroyModelMixin
  • RetrieveModelMixin
  • UpdateModelMixin
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin

使用 APIView 的視圖層類:

class BookAPIView(APIView):
    def get(self, request):
        book_list = models.Book.objects.all()
        ser = BookModelSerializer(instance=book_list, many=True)  # 獲取多個資源用 many=True
        print(ser.data)
        return Response(ser.data)

    def post(self, request):
        ser = BookModelSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})
        return Response({'code': 101, 'msg': '新增失敗', 'data': ser.errors})


class BookSetAPIView(APIView):
    def get(self, request, pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        ser = BookModelSerializer(instance=book_obj)
        return Response(ser.data)

    def put(self, request, pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        ser = BookModelSerializer(instance=book_obj, data=request.data)  # 修改是既有instance 也有data才行
        if ser.is_valid():
            ser.save()
            return Response({'status': 100, 'msg': '修改成功', 'data': ser.data})
        return Response({'status': 100, 'msg': '修改失敗', 'data': ser.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'status': 100, 'msg': '刪除成功'})

使用 GenericAPIView 的視圖層類:

和繼承 APIView 的區別就是,多了querysetserializer_class屬性,還有get_queryset等方法,而且無論換了什麼模型表(Auth、Publish),只需要改變querysetserializer_class屬性即可,五個介面方法均不需要改變

class BookGeneric(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer

    def get(self, request):
        quertset = self.get_queryset()
        serializer_class = self.get_serializer(instance=quertset, many=True)
        print(serializer_class.data)
        return Response(serializer_class.data)

    def post(self, request):
        serializer_class = self.get_serializer(data=request.data)
        if serializer_class.is_valid():
            serializer_class.save()
            return Response({'code': 100, 'msg': '新增成功', 'data': serializer_class.data})
        return Response({'code': 101, 'msg': '新增失敗', 'data': serializer_class.errors})


class BookSetGeneric(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer

    def get(self, request, pk):
        queryset = self.get_object()
        serializer_class = self.get_serializer(instance=queryset)
        return Response(serializer_class.data)

    def put(self, request, pk):
        queryset = self.get_object()
        serializer_class = self.get_serializer(instance=queryset, data=request.data)  # 修改是既有instance 也有data才行
        if serializer_class.is_valid():
            serializer_class.save()
            return Response({'status': 100, 'msg': '修改成功', 'data': serializer_class.data})
        return Response({'status': 100, 'msg': '修改失敗', 'data': serializer_class.errors})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'status': 100, 'msg': '刪除成功'})

繼承 GenericAPIView 和5個視圖擴展類:

五個視圖擴展類封裝了原來 GeneriacAPIView 類所需要書寫的五個介面方法

獲取模型類所有數據對象(get方法)和修改數據(post方法),書寫的方法和原來 GeneriacAPIView 類中的五個介面幾乎一致:

class ListModelMixin:
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

class CreateModelMixin:
    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)

獲取單個模型類數據對象、修改數據、刪除數據三個需要傳入pk值的視圖擴展類:

class RetrieveModelMixin:
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

class UpdateModelMixin:
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, '_prefetched_objects_cache', None):
            instance._prefetched_objects_cache = {}
        return Response(serializer.data)

class DestroyModelMixin:
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

視圖層類:

繼承了這些視圖擴展類,我們就可以使用類中封裝的介面函數,更進一步精簡視圖層類的介面代碼了

class BookGenericMinxin(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects
    serializer_class = BookModelSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookGenericSetMinxin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects
    serializer_class = BookModelSerializer

    def get(self, request, pk):
        return self.retrieve(request)

    def put(self, request, pk):
        return self.update(request)

    def delete(self, request, pk):
        return self.destroy(request)

序列化類:

class BookModelSerializer(ModelSerializer):  # 繼承的是 ModelSerializer
    class Meta:
        model = Book
        fields = ['id', 'name', 'price', 'publish', 'authors', 'author_list', 'publish_info']  # 註意別漏寫 fields

        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_only': True}
        }

路由層:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', views.BookAPIView.as_view()),
    path('book/<int:pk>/', views.BookSetAPIView.as_view()),
    path('book1/', views.BookGeneric.as_view()),
    path('book1/<int:pk>/', views.BookSetGeneric.as_view()),
    path('book2/', views.BookGenericMinxin.as_view()),
    path('book2/<int:pk>/', views.BookGenericSetMinxin.as_view()),
]

封裝程度越來越高,代碼越來越精簡

GenericAPIView 的9個視圖子類

這九個視圖子類,連 getpostputgetdelete 五個介面都幫我們寫完了,我們在書寫GenericAPIView視圖層類時,只需要導入這九個試圖子類來繼承,就可以不用書寫五個方法了,需要什麼介面導入什麼模塊。

單獨的類:

from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView

組合:

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
  • CreateAPIView

  • ListAPIView

  • RetrieveAPIView

  • UpdateAPIView

  • DestroyAPIView

  • ListCreateAPIView

  • RetrieveUpdateDestroyAPIView

  • RetrieveDestroyAPIView

  • RetrieveUpdateAPIView

其實,它們就是繼承了GenericAPIView類,並且與五個視圖擴展類進行了組合繼承,並把介面函數也添加上罷了。pk使用 *args 和 **kwargs 來取締了

class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

class RetrieveAPIView(mixins.RetrieveModelMixin,
                      GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

class UpdateAPIView(mixins.UpdateModelMixin,
                    GenericAPIView):
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

class DestroyAPIView(mixins.DestroyModelMixin,
                     GenericAPIView):
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

# 組合的就不逐一列舉了,原理一樣
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

這樣,我們在書寫視圖層類更加精簡了:

class BookView(ListCreateAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer


class BookSetView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer

路由書寫:

urlpatterns = [
    path('book3/', views.BookView.as_view()),
    path('book3/<int:pk>/', views.BookSetView.as_view()),
]

ViewSetMixin 介紹

ViewSetMixin的源碼可以看到,它把as_view方法進行了重寫,在路由層調用視圖類時,如果類第一個繼承的時ViewSetMixin,會優先調用它的as_view方法,需要傳入位置參數 (一個字典)actions,而且由actions.items(),actions是一個字典。

這樣一來我們不使用到 九個視圖子類給我們封裝的五個介面方法(get、post、put、delete、patch),可以直接繼承 ViewSetMixin, ListModelMixin, CreateModelMixin, GenericAPIView。因為在路由中會傳進來 get 等五個字典key,賦值對象地址後可直接調用。

記住:繼承ViewSetMixin 之後書寫路由時需要傳入 actions 參數

class ViewSetMixin:
    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # 例子 method = 'get',action='list'
            for method, action in actions.items():
                # 獲取 list() 方法的對象地址
                handler = getattr(self, action)
                # 相當於 self.get = list,把lsit方法賦值給了self.get,發送get請求時觸發,相當於觸發了 ListModelMixin 的 list() 方法
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs)
        view.actions = actions
        return csrf_exempt(view)

導入

from rest_framework.viewsets import ViewSetMixin

路由層:

as_view()需要傳入字典:{“請求方式”: “方法名”}

註意字典中分別是五個介面的請求方式和對應的五個視圖擴展類封裝好的方法

urlpatterns = [
    path('book4/', views.BookViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
    path('book4/<int:pk>/', views.BookViewSetPk.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'delete'}))
]

視圖層類:

class BookViewSet(ViewSetMixin, ListCreateAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer


class BookViewSetPk(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = Book.objects
    serializer_class = BookModelSerializer

Viewset系列

from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet, ModelViewSet
  • ViewSetMixin
  • ViewSet
  • GenericViewSet
  • ModelViewSet

ViewSet

繼承了 ViewSetMixinAPIView

class ViewSet(ViewSetMixin, views.APIView):
    """
    The base ViewSet class does not provide any actions by default.
    """
    pass

GenericViewSet

繼承了 ViewSetMixinGenericAPIView

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    """
    The GenericViewSet class does not provide any actions by default,
    but does include the base set of generic view behavior, such as
    the `get_object` and `get_queryset` methods.
    """
    pass

ModelViewsetMinx

包含了五個視圖擴展類和 GenericViewSet

這樣繼承了 ModelViewSet的試圖層類可以不用把五個介面分開兩個類來寫了

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass
class BookViewSet(ModelViewSet):
    queryset = Book.objects
    serializer_class = BookModelSerializer

繼承了 ViewSetMixin 之後,路由就要都要寫成這樣:

urlpatterns = [
    path('book4/', views.BookViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
    path('book4/<int:pk>/', views.BookViewSetPk.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'delete'}))
]

drf 提供了自動生成這樣兩條路由與視圖函數對應關係的功能模塊 routers

用法:

# 導入
from rest_framework.routers import DefaultRouter, SimpleRouter

# 實例化對象並註冊路由
router = DefaultRouter()
router.register('book4', views.BookViewSet, 'book4')

添加到路由列表中

1、路由分發

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include(router.urls)),
]

2、直接列表相加

urlpatterns += router.urls

image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • flex三連問,幫助我們更好的理解佈局利器 問題: flex的值 auto, none, 0, 1, initial分別是什麼?有什麼作用?有什麼表現? flex-basis和width的區別?單值flex-basis:0與auto的區別?flex-basis:100px與width:100px一樣 ...
  • 前言 小學數學老師教過我們,0.1 + 0.2 = 0.3,但是為什麼在我們在瀏覽器的控制臺中輸出卻是0.30000000000000004? 除了加法有這個奇怪的現象,帶小數點的減法和乘除計算也會得出意料之外的結果 console.log(0.3 - 0.1) // 0.1999999999999 ...
  • 註意如果你的mac是M1處理器 那抱歉當前文章可能不支持了,因為當前模擬器不支持。 3步完成mac uniapp 模擬器配置 1.下載網易mumu模擬器 https://mumu.163.com/mac/index.html 2.安裝 設置 下載完成後安裝運行就是這樣的 選擇屏幕旋轉 手機模式 3. ...
  • 具體示例 //代碼 console.log(JSON.stringify({ x: 5, y: 6 },null,2)); //輸出結果 { "x": 5, "y": 6 } JSON.stringify() 介紹 JSON.stringify()方法將一個JavaScript對象或值轉換為JSON ...
  • 原型模式不是通過new生成新的對象,而使通過複製進行生成; 原型模式適用於相同類型的多個對象的生成; 原型模式分為兩種:淺克隆/淺表副本(Shallow Clone)和深克隆/深表副本(Deep Clone); 淺克隆:Shallow Clone,只複製值類型變數,不複製引用類型變數的克隆;(只複製 ...
  • 相比於工廠模式,抽象工廠模式的每個工廠可以創建產品系列,而不是一個產品; 抽象工廠用到的技術:介面、多態、配置文件、反射; 抽象工廠模式的設計原則: 實現客戶端創建產品和使用產品的分離,客戶端無須瞭解創建的細節,符合迪米特法則; 客戶端面向介面定義產品,符合依賴倒置原則; 客戶端面向介面定義工廠,而 ...
  • 外觀(Facade)模式,又叫做門面模式,是一種通過為多個複雜的子系統提供一個一致的介面,使這些子系統更加容易被訪問的模式。比如說我們日常生活中醫院的分診台,就是實現統一訪問介面的特性: 一、外觀模式介紹 外觀模式提供一個統一介面,用來訪問子系統的一系列介面,從而讓子系統更容易使用。這個子系統可以有 ...
  • 本篇是根據 GopherCon SG 2019 “Understanding Allocations” 演講的學習筆記。 Understanding Allocations: the Stack and the Heap - GopherCon SG 2019 - YouTube 理解分配:棧和堆 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...