实现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代码了。
下一篇记录一下前端的实现
完整代码