#!/bin/python #coding: utf-8 # +------------------------------------------------------------------- # | version:1.3 # +------------------------------------------------------------------- # | django-vue-lyadmin # +------------------------------------------------------------------- # | Author: lybbn # +------------------------------------------------------------------- # | QQ: 1042594286 # +------------------------------------------------------------------- # | Date: 2023/10/17 # +------------------------------------------------------------------- # ------------------------------ # 表单构建--viewset # ------------------------------ from django.template import Template,Context def lyGenerateViewSet(object): fields = ['beginAt','endAt'] object_new = [] #自定义导出 canExport = False export_field_dict = {} export_download_filename = "导出%s数据"%object['formConfig']['modelVerboseName'] #自定义SerializerMethodField ForeignKeyList = [] representation = [] for c in object['widgetList']: field_name = c['options']['crudField']['field_name'] verbose_name = c['options']['crudField']['verbose_name'] field_type = c['options']['crudField'].get('field_type','') foreign_key = c['options']['crudField']['foreign_key'] form_type = c.get('type','') if form_type in ['checkbox','cascader']: f_data = f"""ret['{field_name}'] = ast_convert(ret['{field_name}'])""" representation.append(f_data) if c['options']['crudField']['can_search']: if field_type in ['DateField','DateTimeField'] and c['options']['crudField']['search_type'] == 'range': fields.append(field_name+'_beginAt') fields.append(field_name+'_endAt') else: fields.append(field_name) object_new.append(filter_column(c['options']['crudField'])) if c['options']['crudField'].get('can_export',False): canExport = True if field_type in ['ForeignKey','ManyToManyField','OneToOneField']: gname = "%s_lyformbuilder_name"%field_name export_field_dict[gname] = verbose_name else: export_field_dict[field_name] = verbose_name if field_type == 'ForeignKey' or field_type == 'OneToOneField': f_class_name = foreign_key['class_name'] f_value = foreign_key['value'] f_label = foreign_key['label'] if f_class_name and f_value and f_label: gname = "%s_lyformbuilder_name"%field_name s_data = f"""{gname}=serializers.SerializerMethodField(read_only=True) def get_{gname}(self,obj): if obj.{field_name}_id: return obj.{field_name}.{f_label} return '' """ ForeignKeyList.append(s_data) exportData = { 'canExport':canExport, 'export_field_dict':export_field_dict, 'export_download_filename':export_download_filename } viewset_code = """# -*- coding: utf-8 -*- #此文件请放在lyFormBuilder的views目录中 import django_filters from rest_framework import serializers from utils.viewset import CustomModelViewSet from utils.serializers import CustomModelSerializer from utils.common import ast_convert from apps.lyFormBuilder.models.models_{{object.formConfig.modelClassName}} import {{ object.formConfig.modelClassName }} class {{ object.formConfig.modelClassName }}FilterSet(django_filters.rest_framework.FilterSet): \"\"\" {{object.formConfig.modelVerboseName}} 过滤器 URL格式:http://127.0.0.1:8000/?beginAt=2020-12-02 12:00:00&endAt=2021-12-13 12:00:00 field_name: 过滤字段名,一般应该对应模型中字段名 lookup_expr: 查询时所要进行的操作,和ORM中运算符一致 fields:指明过滤字段,可以是列表,也可以字典 exclude = ['password'] 排除字段,不允许使用列表中字典进行过滤 自定义字段名可以和模型中不一致,但一定要用参数field_name指明对应模型中的字段名 \"\"\" #开始时间 beginAt = django_filters.DateTimeFilter(field_name='create_datetime', lookup_expr='gte') # 指定过滤的字段 #结束时间 endAt = django_filters.DateTimeFilter(field_name='create_datetime', lookup_expr='lte'){% for c in object_new %} {{ c | safe }}{% endfor %} class Meta: model = {{object.formConfig.modelClassName}} fields = {{fields | safe}} class {{ object.formConfig.modelClassName }}Serializer(CustomModelSerializer): \"\"\" {{ object.formConfig.modelClassName }} 序列化器 \"\"\"{% for f in ForeignKeyList %} {{ f|safe }}{% endfor %}{% if representation %} def to_representation(self, instance): ret = super().to_representation(instance){% for r in representation %} {{ r|safe }}{% endfor %} return ret {% endif %} class Meta: model = {{ object.formConfig.modelClassName }} read_only_fields = ["id"] fields = '__all__' class {{ object.formConfig.modelClassName }}ViewSet(CustomModelViewSet): \"\"\" {{ object.formConfig.modelClassName }} 接口 \"\"\" queryset = {{object.formConfig.modelClassName}}.objects.all() serializer_class = {{ object.formConfig.modelClassName}}Serializer filterset_class = {{ object.formConfig.modelClassName }}FilterSet {% if exportData.canExport %} export_download_filename = "{{exportData.export_download_filename}}" export_field_dict = {{exportData.export_field_dict|safe}} {% endif %} """ context = Context({'object': object,'object_new':object_new,'fields':fields,'exportData':exportData,'ForeignKeyList':ForeignKeyList,'representation':representation}) return Template(viewset_code).render(context) def filter_column(field): search_type_turn = lookup_expr_translate(field.get('search_type',None)) if field['field_type'] == "BooleanField": if search_type_turn == "isnull": return "%s = django_filters.BooleanFilter(field_name='%s',lookup_expr='isnull')"%(field['field_name'],field['field_name']) return "%s = django_filters.BooleanFilter(field_name='%s')" % (field['field_name'], field['field_name']) # return "%s = django_filters.CharFilter(field_name='%s')" % (field['field_name'], field['field_name']) elif field['field_type'] in ['CharField','TextField']: return "%s = django_filters.CharFilter(field_name='%s',lookup_expr='%s')" % (field['field_name'], field['field_name'],search_type_turn) elif field['field_type'] in ['DateTimeField']: if search_type_turn in ['range']: return f"""{field['field_name']}_beginAt = django_filters.DateTimeFilter(field_name='{field['field_name']}', lookup_expr='gte') {field['field_name']}_endAt = django_filters.DateTimeFilter(field_name='{field['field_name']}', lookup_expr='lte')""" else: return "%s = django_filters.DateTimeFilter(field_name='%s',lookup_expr='%s')" % (field['field_name'], field['field_name'],search_type_turn) elif field['field_type'] in ['DateField']: if search_type_turn in ['range']: return f"""{field['field_name']}_beginAt = django_filters.DateFilter(field_name='{field['field_name']}', lookup_expr='gte') {field['field_name']}_endAt = django_filters.DateFilter(field_name='{field['field_name']}', lookup_expr='lte')""" else: return "%s = django_filters.DateFilter(field_name='%s',lookup_expr='%s')" % (field['field_name'], field['field_name'],search_type_turn) else: return "%s = django_filters.CharFilter(field_name='%s',lookup_expr='%s')" % (field['field_name'], field['field_name'],search_type_turn) def lookup_expr_translate(search_type): search_type_turn = "icontains" if search_type == "=": search_type_turn = "exact" elif search_type == ">": search_type_turn = "gt" elif search_type == "<": search_type_turn = "lt" elif search_type == ">=": search_type_turn = "gte" elif search_type == "<=": search_type_turn = "lte" elif search_type == "isnull": search_type_turn = "isnull" elif search_type == "in": search_type_turn = "in" elif search_type == "range": search_type_turn = "range" elif search_type == "icontains": search_type_turn = "icontains" elif search_type == "contains": search_type_turn = "contains" elif search_type == "startswith": search_type_turn = "startswith" elif search_type == "istartswith": search_type_turn = "istartswith" elif search_type == "endswith": search_type_turn = "endswith" elif search_type == "iendswith": search_type_turn = "iendswith" elif search_type == "year": search_type_turn = "year" elif search_type == "year__lt": search_type_turn = "year__lt" elif search_type == "year__lte": search_type_turn = "year__lte" elif search_type == "year__gt": search_type_turn = "year__gt" elif search_type == "year__gte": search_type_turn = "year__gte" elif search_type == "month": search_type_turn = "month" elif search_type == "day": search_type_turn = "day" return search_type_turn