Django 使用models.Manager擴展查詢的方法

先來擴展一下使用.all()查詢時,通過傳入自定義參數返回不同的數據集

1、在模型中使用models.Manager

# 自定義擴展.all()方法
class MiddlewareRegionSplitManager(models.Manager):
    def all(self, user=None):
        if user:
        	# 當沒有 region_split 並且 group_id 爲1時返回所有數據 否則只返回與user.region_split所匹配的數據
            if not user.region_split and user.group_id == 1:
                return super().all()
            else:
                return super().all().filter(region_split=user.region_split)
        # 如果沒有傳入user參數 返回所有數據
        return super().all()

# 當所有模型都包含這些字段時,這裏可以定義一個基本模型,讓其他模型都繼承與它
class BaseModel(models.Model):
    sort = models.IntegerField(default=1, null=True, blank=True, verbose_name='排序')
    content = models.TextField(default='', null=True, blank=True, verbose_name='描述')
    sort_time = models.DateTimeField(auto_now_add=True, verbose_name='排序時間')
    created = models.DateTimeField(auto_now_add=True, verbose_name='創建時間')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新時間')
    region_split = models.IntegerField(null=True, blank=True, verbose_name='所屬區域')
    # 定義使用的models.Manager
    objects = MiddlewareRegionSplitManager()

    class Meta:
        abstract = True

# 定義一個系統字典模型
class ConfDict(SoftDeleteModel, BaseModel):
    dict_title = models.CharField(max_length=255, verbose_name='字典標題')
    dict_key = models.IntegerField(default=0, verbose_name='字典鍵值')
    dict_type = models.IntegerField(default=0, verbose_name='字典類型')

    class Meta:
        db_table = 'A_ConfDict_Table'
        verbose_name = '系統字典表'
        verbose_name_plural = verbose_name
        # unique_together = (('dict_title', 'region_split'), ) 設置聯合唯一

2、在視圖中使用

class CongDictViewset(ModelViewSet):
    '''
    修改局部數據
    create:  創建系統字典
    retrieve:  檢索某個系統字典
    update:  更新系統字典
    destroy:  刪除系統字典
    list:  獲取系統字典列表
    '''
    queryset = ConfDict.objects.all().order_by('-updated')
    serializer_class = ConfDictSerializer
    authentication_classes = [JWTAuthentication, ]
    permission_classes = []
    # 頻率驗證
    throttle_classes = [VisitThrottle]
    # drf 過濾&搜索&排序
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter,)
    # 搜索
    search_fields = ('dict_title', 'content',)
    # 過濾
    filter_fields = ('dict_type',)
    # 排序
    ordering_fields = ('updated', 'sort_time', 'created',)
    pagination_class = Pagination

    def get_permissions(self):
    	# 指定get查詢時 不需要權限
        if self.action == 'list':
            return []
        else:
            return [BasePermission()]
    
    def get_queryset(self):
        if self.request.auth:
        	# 當用戶登錄了 得到用戶 user 參數 傳入 .all()方法 來返回不同的結果
            return ConfDict.objects.all(user=self.request.user).order_by('-updated')
        # 當沒有登錄時正常返回
        return ConfDict.objects.all().order_by('-updated')

3、重新定義自己的方法

# 修改定義的 MiddlewareRegionSplitManager 類 如下示
class MiddlewareRegionSplitManager(models.Manager):
	def region(self, user=None):
        queryset = super().get_queryset()
        if user:
        	if not user.region_split and user.group_id == 1:
                pass
            else:
                queryset = queryset.filter(region_split=user.region_split)
        return queryset

4、在試圖中使用

將 get_queryset 方法修改如下示

def get_queryset(self):
	if self.request.auth:
		# 當用戶登錄了 得到用戶 user 參數 傳入 .all()方法 來返回不同的結果
	    return ConfDict.objects.all().region(user=user).order_by('-updated')
	# 當沒有登錄時正常返回
	return ConfDict.objects.all().order_by('-updated')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章