django+react短时间搭建一套增删查改项目思路(二)

965 阅读1分钟

实现create_crud命令

实现crud的功能,实际上就是每个模块下的viewsets.py, serializers.py, urls.py中根据models写入文件。而每一个模块及模块下的model都是能获取的。

class Command(BaseCommand):
    help = "create crud code according ModelViewSet"

    def handle(self, *args, **options):
        exclude_apps = [
            "django.contrib.admin",
            "django.contrib.auth",
            "django.contrib.contenttypes",
            "django.contrib.sessions",
            "django.contrib.messages",
            "django.contrib.staticfiles",
            "rest_framework",
            "django_filters",
        ]
        configs = apps.get_app_configs()
        gen = CodeGenerator()

        create_configs = []
        for config in configs:
            # django自带的模块不需要创建
            if config.name in exclude_apps:
                pass
            else:
                gen.init_files(config.path)
                create_configs.append(config)
        
        gen.write_file_header(create_configs) # 初始化文件
        gen.batch_gen_code(create_configs) # 写入增删查改代码

        self.stdout.write("success")

这里初始化文件,主要就是import相关的模块

for config in configs:
    filter_header = "from django_filters.rest_framework import FilterSet"
    serializer_header = "from rest_framework.serializers import ModelSerializer"
    viewset_header = "from restframework_core.viewsets import CustomModelViewSet"
    url_header = "from django.conf.urls import url, re_path, include\n\nfrom rest_framework.routers import DefaultRouter"

    filter_path = path.join(self.parent_path, config.name, "filters.py")
    serializer_path = path.join(self.parent_path, config.name, "serializers.py")
    viewset_path = path.join(self.parent_path, config.name, "viewsets.py")
    url_path = path.join(self.parent_path, config.name, "urls.py")

    models = config.get_models()
    # ...write import models
    # ...write files

之后便是循环model根据模版写入相应的代码了

    # viewset模版代码
    @property
    def viewset_template(self):
        return f"""class {self.name}ViewSet(CustomModelViewSet):
    serializer_class = {self.name}Serializer
    filter_class = {self.name}Filter
    queryset = {self.name}.objects.all()
        """
    
    #serializer模版代码
    @property
    def serializer_template(self):
        return f"""class {self.name}Serializer(serializers.ModelSerializer):
    class Meta:
        model = {self.name}
        exclude = ('updated', 'deleted')
        """
        
    #url模版代码
    @property
    def url_template(self):
        lower = self._lower_name
        return f"""router.register(r'{lower}', {self.name}ViewSet, basename="{lower}")"""

当然还可以加入Filter的生成以及相关接口文档的生成模版,最后将model传入,按模块写入到相应的文件中。

生成json文件

同理根据相应的model元数据,生成json

    def gen_model_json(self, model):
        file_name = f"{model.__name__}.json"
        full_path = os.path.join(self.base_path, file_name)

        properties = {}
        for field in model._meta.fields:
            if field.name == "id" or field.name == "deleted" or field.name == "updated":
                continue
            field_data = {
                "title": str(field.verbose_name),
                "required": "false" if field.null else "true",
            }

            choice_data = self._get_choices_data(field) # 获取选项枚举
            if choice_data:
                field_data["enum"] = choice_data

            field_type = self._get_type_data(field)
            field_data["type"] = field_type

            field_name = field.name

            properties[field_name] = field_data
        
        data = {"type": "object", "properties": properties}

        with open(full_path, "w") as f:
            json.dump(data, f, ensure_ascii=False)

这样创建model之后,执行2个命令就能生成后端的api代码了。 下一篇记录一下前端的实现
完整代码