mirror of https://github.com/jumpserver/jumpserver
				
				
				
			fix: Solve audit job and variable bugs
							parent
							
								
									1ee57cfda0
								
							
						
					
					
						commit
						fcdc2b9510
					
				| 
						 | 
				
			
			@ -66,7 +66,7 @@ class JobsAuditViewSet(OrgModelViewSet):
 | 
			
		|||
    search_fields = ['creator__name']
 | 
			
		||||
    filterset_fields = ['creator__name']
 | 
			
		||||
    serializer_class = JobsAuditSerializer
 | 
			
		||||
    ordering = ['-is_periodic', '-date_created']
 | 
			
		||||
    ordering = ['-is_periodic', '-date_updated']
 | 
			
		||||
    http_method_names = ['get', 'options', 'patch']
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,8 +35,14 @@ class JobLogSerializer(JobExecutionSerializer):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class JobsAuditSerializer(JobSerializer):
 | 
			
		||||
    material = serializers.ReadOnlyField(label=_("Command"))
 | 
			
		||||
    summary = serializers.ReadOnlyField(label=_("Summary"))
 | 
			
		||||
 | 
			
		||||
    class Meta(JobSerializer.Meta):
 | 
			
		||||
        fields = JobSerializer.Meta.fields
 | 
			
		||||
        read_only_fields = [
 | 
			
		||||
            "id", 'name', 'args', 'material', 'type', 'crontab', 'interval', 'date_last_run', 'summary', 'created_by'
 | 
			
		||||
        ]
 | 
			
		||||
        fields = read_only_fields + ['is_periodic']
 | 
			
		||||
 | 
			
		||||
    def validate(self, attrs):
 | 
			
		||||
        allowed_fields = {'is_periodic'}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ msgid ""
 | 
			
		|||
msgstr ""
 | 
			
		||||
"Project-Id-Version: JumpServer 0.3.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2024-11-11 19:17+0800\n"
 | 
			
		||||
"POT-Creation-Date: 2024-11-13 11:11+0800\n"
 | 
			
		||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
 | 
			
		||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
 | 
			
		||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
 | 
			
		||||
| 
						 | 
				
			
			@ -593,7 +593,7 @@ msgstr "结束日期"
 | 
			
		|||
#: accounts/models/automations/change_secret.py:44
 | 
			
		||||
#: assets/models/automations/base.py:113
 | 
			
		||||
#: assets/serializers/automations/base.py:39 audits/models.py:208
 | 
			
		||||
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:239
 | 
			
		||||
#: audits/serializers.py:69 ops/models/base.py:49 ops/models/job.py:239
 | 
			
		||||
#: terminal/models/applet/applet.py:331 terminal/models/applet/host.py:140
 | 
			
		||||
#: terminal/models/component/status.py:30
 | 
			
		||||
#: terminal/models/virtualapp/virtualapp.py:99
 | 
			
		||||
| 
						 | 
				
			
			@ -665,7 +665,7 @@ msgstr "触发方式"
 | 
			
		|||
 | 
			
		||||
#: accounts/models/automations/push_account.py:16 acls/models/base.py:41
 | 
			
		||||
#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81
 | 
			
		||||
#: audits/models.py:92 audits/serializers.py:84
 | 
			
		||||
#: audits/models.py:92 audits/serializers.py:99
 | 
			
		||||
#: authentication/serializers/connect_token_secret.py:119
 | 
			
		||||
#: authentication/templates/authentication/_access_key_modal.html:34
 | 
			
		||||
#: perms/serializers/permission.py:52 perms/serializers/permission.py:74
 | 
			
		||||
| 
						 | 
				
			
			@ -884,8 +884,8 @@ msgstr "类别"
 | 
			
		|||
#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20
 | 
			
		||||
#: assets/models/cmd_filter.py:74 assets/models/platform.py:96
 | 
			
		||||
#: assets/serializers/asset/common.py:146 assets/serializers/platform.py:159
 | 
			
		||||
#: assets/serializers/platform.py:171 audits/serializers.py:53
 | 
			
		||||
#: audits/serializers.py:170
 | 
			
		||||
#: assets/serializers/platform.py:171 audits/serializers.py:68
 | 
			
		||||
#: audits/serializers.py:185
 | 
			
		||||
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:153
 | 
			
		||||
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
 | 
			
		||||
#: terminal/models/component/storage.py:58
 | 
			
		||||
| 
						 | 
				
			
			@ -958,7 +958,7 @@ msgstr "ID"
 | 
			
		|||
#: acls/templates/acls/user_login_reminder.html:8
 | 
			
		||||
#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54
 | 
			
		||||
#: audits/models.py:90 audits/models.py:172 audits/models.py:271
 | 
			
		||||
#: audits/serializers.py:171 authentication/models/connection_token.py:32
 | 
			
		||||
#: audits/serializers.py:186 authentication/models/connection_token.py:32
 | 
			
		||||
#: authentication/models/ssh_key.py:22 authentication/models/sso_token.py:16
 | 
			
		||||
#: notifications/models/notification.py:12
 | 
			
		||||
#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63
 | 
			
		||||
| 
						 | 
				
			
			@ -1587,7 +1587,7 @@ msgid "Login city"
 | 
			
		|||
msgstr "登录城市"
 | 
			
		||||
 | 
			
		||||
#: acls/templates/acls/user_login_reminder.html:11 audits/models.py:197
 | 
			
		||||
#: audits/models.py:266 audits/serializers.py:68
 | 
			
		||||
#: audits/models.py:266 audits/serializers.py:83
 | 
			
		||||
msgid "User agent"
 | 
			
		||||
msgstr "用户代理"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2821,7 +2821,7 @@ msgid "Finished"
 | 
			
		|||
msgstr "结束"
 | 
			
		||||
 | 
			
		||||
#: audits/const.py:46 settings/serializers/terminal.py:6
 | 
			
		||||
#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:174
 | 
			
		||||
#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:182
 | 
			
		||||
#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:57
 | 
			
		||||
#: terminal/serializers/session.py:113
 | 
			
		||||
msgid "Terminal"
 | 
			
		||||
| 
						 | 
				
			
			@ -2866,7 +2866,7 @@ msgstr "作业审计日志"
 | 
			
		|||
msgid "Remote addr"
 | 
			
		||||
msgstr "远端地址"
 | 
			
		||||
 | 
			
		||||
#: audits/models.py:61 audits/serializers.py:38
 | 
			
		||||
#: audits/models.py:61 audits/serializers.py:53
 | 
			
		||||
msgid "Operate"
 | 
			
		||||
msgstr "操作"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2891,12 +2891,12 @@ msgstr "会话"
 | 
			
		|||
msgid "File transfer log"
 | 
			
		||||
msgstr "文件传输"
 | 
			
		||||
 | 
			
		||||
#: audits/models.py:94 audits/serializers.py:86
 | 
			
		||||
#: audits/models.py:94 audits/serializers.py:101
 | 
			
		||||
msgid "Resource Type"
 | 
			
		||||
msgstr "资源类型"
 | 
			
		||||
 | 
			
		||||
#: audits/models.py:95 audits/models.py:98 audits/models.py:144
 | 
			
		||||
#: audits/serializers.py:85 labels/serializers.py:46
 | 
			
		||||
#: audits/serializers.py:100 labels/serializers.py:46
 | 
			
		||||
msgid "Resource"
 | 
			
		||||
msgstr "资源"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2938,7 +2938,7 @@ msgstr "登录方式"
 | 
			
		|||
msgid "Login IP"
 | 
			
		||||
msgstr "登录 IP"
 | 
			
		||||
 | 
			
		||||
#: audits/models.py:200 audits/serializers.py:52
 | 
			
		||||
#: audits/models.py:200 audits/serializers.py:67
 | 
			
		||||
#: authentication/templates/authentication/_mfa_confirm_modal.html:14
 | 
			
		||||
#: users/forms/profile.py:63 users/models/user/__init__.py:79
 | 
			
		||||
#: users/serializers/profile.py:70
 | 
			
		||||
| 
						 | 
				
			
			@ -2982,20 +2982,20 @@ msgstr "下线用户会话"
 | 
			
		|||
msgid "Creator"
 | 
			
		||||
msgstr "创建者"
 | 
			
		||||
 | 
			
		||||
#: audits/serializers.py:69
 | 
			
		||||
#: audits/serializers.py:84
 | 
			
		||||
msgid "Reason display"
 | 
			
		||||
msgstr "原因描述"
 | 
			
		||||
 | 
			
		||||
#: audits/serializers.py:70 audits/serializers.py:184
 | 
			
		||||
#: audits/serializers.py:85 audits/serializers.py:199
 | 
			
		||||
msgid "Auth backend display"
 | 
			
		||||
msgstr "认证方式"
 | 
			
		||||
 | 
			
		||||
#: audits/serializers.py:134
 | 
			
		||||
#: audits/serializers.py:149
 | 
			
		||||
#, python-format
 | 
			
		||||
msgid "%s %s this resource"
 | 
			
		||||
msgstr "用户 %s %s 了当前资源"
 | 
			
		||||
 | 
			
		||||
#: audits/serializers.py:172 authentication/models/connection_token.py:47
 | 
			
		||||
#: audits/serializers.py:187 authentication/models/connection_token.py:47
 | 
			
		||||
#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80
 | 
			
		||||
#: tickets/models/ticket/apply_application.py:31
 | 
			
		||||
#: tickets/models/ticket/apply_asset.py:20 users/models/user/__init__.py:98
 | 
			
		||||
| 
						 | 
				
			
			@ -4719,7 +4719,7 @@ msgid ""
 | 
			
		|||
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
 | 
			
		||||
msgstr "文件大小超过最大限制。请选择小于 {limit}MB 的文件。"
 | 
			
		||||
 | 
			
		||||
#: ops/api/job.py:231
 | 
			
		||||
#: ops/api/job.py:235
 | 
			
		||||
msgid ""
 | 
			
		||||
"The task is being created and cannot be interrupted. Please try again later."
 | 
			
		||||
msgstr "正在创建任务,无法中断,请稍后重试。"
 | 
			
		||||
| 
						 | 
				
			
			@ -4971,7 +4971,7 @@ msgstr "其它参数"
 | 
			
		|||
msgid "Date published"
 | 
			
		||||
msgstr "发布日期"
 | 
			
		||||
 | 
			
		||||
#: ops/models/celery.py:113
 | 
			
		||||
#: ops/models/celery.py:124
 | 
			
		||||
msgid "Celery Task Execution"
 | 
			
		||||
msgstr "Celery 任务执行"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4992,10 +4992,8 @@ msgid "Parameters define"
 | 
			
		|||
msgstr "参数定义"
 | 
			
		||||
 | 
			
		||||
#: ops/models/job.py:159
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Periodic run"
 | 
			
		||||
msgid "Periodic variable"
 | 
			
		||||
msgstr "周期执行"
 | 
			
		||||
msgstr "周期执行变量"
 | 
			
		||||
 | 
			
		||||
#: ops/models/job.py:160
 | 
			
		||||
msgid "Run as"
 | 
			
		||||
| 
						 | 
				
			
			@ -5031,40 +5029,32 @@ msgid "VCS URL"
 | 
			
		|||
msgstr "VCS URL"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:11
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Variable Type"
 | 
			
		||||
msgid "Variable name"
 | 
			
		||||
msgstr "参数类型"
 | 
			
		||||
msgstr "变量名"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:12
 | 
			
		||||
msgid ""
 | 
			
		||||
"The variable name used in the script has a fixed prefix 'jms_' followed by "
 | 
			
		||||
"the input variable name. For example, if the variable name is 'name,' the "
 | 
			
		||||
"final generated environment variable will be 'jms_name'."
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "在脚本使用的变量名称,固定前缀 jms_ + 输入的变量名,例如变量名name,则最终生成环境变量为 jms_name"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:16
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Default"
 | 
			
		||||
msgid "Default Value"
 | 
			
		||||
msgstr "默认"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:18
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Variable Type"
 | 
			
		||||
msgid "Variable type"
 | 
			
		||||
msgstr "参数类型"
 | 
			
		||||
msgstr "变量类型"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:21 ops/serializers/variable.py:23
 | 
			
		||||
#: ops/models/variable.py:21 ops/serializers/variable.py:25
 | 
			
		||||
msgid "ExtraVars"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "额外参数"
 | 
			
		||||
 | 
			
		||||
#: ops/models/variable.py:49 ops/serializers/adhoc.py:16
 | 
			
		||||
#: ops/serializers/job.py:22 ops/serializers/playbook.py:21
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Variable Type"
 | 
			
		||||
msgid "Variable"
 | 
			
		||||
msgstr "参数类型"
 | 
			
		||||
msgstr "变量"
 | 
			
		||||
 | 
			
		||||
#: ops/notifications.py:20
 | 
			
		||||
msgid "Server performance"
 | 
			
		||||
| 
						 | 
				
			
			@ -5126,11 +5116,11 @@ msgstr "任务 ID"
 | 
			
		|||
msgid "You do not have permission for the current job."
 | 
			
		||||
msgstr "你没有当前作业的权限。"
 | 
			
		||||
 | 
			
		||||
#: ops/serializers/variable.py:20
 | 
			
		||||
#: ops/serializers/variable.py:22
 | 
			
		||||
msgid "Variable Type"
 | 
			
		||||
msgstr "参数类型"
 | 
			
		||||
msgstr "变量类型"
 | 
			
		||||
 | 
			
		||||
#: ops/serializers/variable.py:25
 | 
			
		||||
#: ops/serializers/variable.py:27
 | 
			
		||||
msgid ""
 | 
			
		||||
"Each item is on a separate line, with each line separated by a colon. The "
 | 
			
		||||
"part before the colon is the display content, and the part after the colon "
 | 
			
		||||
| 
						 | 
				
			
			@ -6586,8 +6576,6 @@ msgid "Vault"
 | 
			
		|||
msgstr "启用 Vault"
 | 
			
		||||
 | 
			
		||||
#: settings/serializers/feature.py:53
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Provider"
 | 
			
		||||
msgid "Vault provider"
 | 
			
		||||
msgstr "云服务商"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6611,8 +6599,6 @@ msgstr "挂载点"
 | 
			
		|||
 | 
			
		||||
#: settings/serializers/feature.py:94
 | 
			
		||||
#: xpack/plugins/cloud/serializers/account_attrs.py:41
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Client ID"
 | 
			
		||||
msgid "Tenant ID"
 | 
			
		||||
msgstr "客户端 ID"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7899,7 +7885,7 @@ msgstr "远端地址"
 | 
			
		|||
msgid "Application User"
 | 
			
		||||
msgstr "应用用户"
 | 
			
		||||
 | 
			
		||||
#: terminal/models/component/terminal.py:176
 | 
			
		||||
#: terminal/models/component/terminal.py:184
 | 
			
		||||
msgid "Can view terminal config"
 | 
			
		||||
msgstr "可以查看终端配置"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8823,7 +8809,7 @@ msgstr "工单快照"
 | 
			
		|||
msgid "Please try again"
 | 
			
		||||
msgstr "请再次尝试"
 | 
			
		||||
 | 
			
		||||
#: tickets/models/ticket/general.py:481
 | 
			
		||||
#: tickets/models/ticket/general.py:483
 | 
			
		||||
msgid "Super ticket"
 | 
			
		||||
msgstr "超级工单"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1413,5 +1413,6 @@
 | 
			
		|||
    "setVariable": "Set variable",
 | 
			
		||||
    "JobsAudit": "Jobs audit",
 | 
			
		||||
    "JobList": "Job List",
 | 
			
		||||
    "StopJobMsg": "Stop job successfully"
 | 
			
		||||
    "StopJobMsg": "Stop job successfully",
 | 
			
		||||
    "ExtraArgsFormatError": "Format error, please enter according to the requirements"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1418,5 +1418,6 @@
 | 
			
		|||
    "setVariable": "设置参数",
 | 
			
		||||
    "JobsAudit": "作业审计",
 | 
			
		||||
    "JobList": "作业列表",
 | 
			
		||||
    "StopJobMsg": "停止成功"
 | 
			
		||||
    "StopJobMsg": "停止成功",
 | 
			
		||||
    "ExtraArgsFormatError": "格式错误,请按要求输入"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,9 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
from django.core.exceptions import ObjectDoesNotExist
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from rest_framework import serializers
 | 
			
		||||
from rest_framework.exceptions import ValidationError
 | 
			
		||||
 | 
			
		||||
from common.serializers.fields import ReadableHiddenField, LabeledChoiceField, EncryptedField
 | 
			
		||||
from common.serializers.mixin import CommonBulkModelSerializer
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +17,13 @@ __all__ = [
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class VariableSerializer(CommonBulkModelSerializer):
 | 
			
		||||
    name = serializers.CharField(max_length=1024, label=_('Name'), required=True)
 | 
			
		||||
    var_name = serializers.CharField(
 | 
			
		||||
        max_length=1024, required=True, label=_('Variable name'),
 | 
			
		||||
        help_text=_("The variable name used in the script has a fixed prefix 'jms_' followed by the input variable "
 | 
			
		||||
                    "name. For example, if the variable name is 'name,' the final generated environment variable will "
 | 
			
		||||
                    "be 'jms_name'.")
 | 
			
		||||
    )
 | 
			
		||||
    creator = ReadableHiddenField(default=serializers.CurrentUserDefault())
 | 
			
		||||
    type = LabeledChoiceField(
 | 
			
		||||
        choices=FieldType.choices, default=FieldType.text, label=_("Variable Type")
 | 
			
		||||
| 
						 | 
				
			
			@ -82,64 +91,68 @@ class PlaybookVariableSerializer(VariableSerializer):
 | 
			
		|||
        fields = VariableSerializer.Meta.fields
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_dynamic_text_choices(options):
 | 
			
		||||
    """
 | 
			
		||||
    动态创建一个 TextChoices 子类。`options` 应该是一个列表,
 | 
			
		||||
    格式为 [(value1, display1), (value2, display2), ...]
 | 
			
		||||
    """
 | 
			
		||||
    attrs = {
 | 
			
		||||
        key.upper(): value for value, key in options
 | 
			
		||||
    }
 | 
			
		||||
    attrs['choices'] = options
 | 
			
		||||
    return type('DynamicTextChoices', (models.TextChoices,), attrs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VariableFormDataSerializer(serializers.Serializer):
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        request = self.context.get('request')
 | 
			
		||||
        if not request:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        params = request.query_params
 | 
			
		||||
        if params.get('format') == 'openapi':
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        job = params.get('job')
 | 
			
		||||
        adhoc = params.get('adhoc')
 | 
			
		||||
        playbook = params.get('playbook')
 | 
			
		||||
        if job:
 | 
			
		||||
            variables = Variable.objects.filter(job=job).all()
 | 
			
		||||
        elif adhoc:
 | 
			
		||||
            variables = Variable.objects.filter(adhoc=adhoc).all()
 | 
			
		||||
        else:
 | 
			
		||||
            variables = Variable.objects.filter(playbook=playbook).all()
 | 
			
		||||
 | 
			
		||||
        if not any([job, adhoc, playbook]):
 | 
			
		||||
            raise ValidationError("One of 'job', 'adhoc', or 'playbook' is required.")
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            variables = Variable.objects.filter(
 | 
			
		||||
                job=job if job else None,
 | 
			
		||||
                adhoc=adhoc if adhoc else None,
 | 
			
		||||
                playbook=playbook if playbook else None
 | 
			
		||||
            ).all()
 | 
			
		||||
        except ObjectDoesNotExist:
 | 
			
		||||
            raise ValidationError("Invalid job, adhoc, or playbook ID.")
 | 
			
		||||
 | 
			
		||||
        dynamic_fields = [var.form_data for var in variables]
 | 
			
		||||
 | 
			
		||||
        if dynamic_fields:
 | 
			
		||||
            for field in dynamic_fields:
 | 
			
		||||
                field_type = field['type']
 | 
			
		||||
                required = field['required']
 | 
			
		||||
                var_name = field["var_name"]
 | 
			
		||||
                label = field["label"]
 | 
			
		||||
                help_text = field['help_text']
 | 
			
		||||
                default = field['default']
 | 
			
		||||
                if field_type == FieldType.text:
 | 
			
		||||
                    self.fields[var_name] = serializers.CharField(
 | 
			
		||||
                        max_length=1024, label=label, help_text=help_text, required=required
 | 
			
		||||
                    )
 | 
			
		||||
                elif field_type == FieldType.select:
 | 
			
		||||
                    extra_args = field.get('extra_args', {})
 | 
			
		||||
                    options = extra_args.get('options', '').splitlines()
 | 
			
		||||
        for field in dynamic_fields:
 | 
			
		||||
            self._add_field(field)
 | 
			
		||||
 | 
			
		||||
                    DynamicFieldType = models.TextChoices(
 | 
			
		||||
                        'DynamicFieldType',
 | 
			
		||||
                        {
 | 
			
		||||
                            option.split(':')[0]: option.split(':')[1] for option in
 | 
			
		||||
                            options
 | 
			
		||||
                        }
 | 
			
		||||
                    )
 | 
			
		||||
                    self.fields[var_name] = LabeledChoiceField(
 | 
			
		||||
                        choices=DynamicFieldType.choices, required=required, label=label,
 | 
			
		||||
                        help_text=help_text
 | 
			
		||||
                    )
 | 
			
		||||
                if required and default is not None:
 | 
			
		||||
                    self.fields[var_name].default = default
 | 
			
		||||
    def _add_field(self, field):
 | 
			
		||||
        field_type = field['type']
 | 
			
		||||
        required = field['required']
 | 
			
		||||
        var_name = field["var_name"]
 | 
			
		||||
        label = field["label"]
 | 
			
		||||
        help_text = field['help_text']
 | 
			
		||||
        default = field.get('default', None)
 | 
			
		||||
 | 
			
		||||
        if field_type == FieldType.text:
 | 
			
		||||
            self.fields[var_name] = serializers.CharField(
 | 
			
		||||
                max_length=1024, label=label, help_text=help_text, required=required
 | 
			
		||||
            )
 | 
			
		||||
        elif field_type == FieldType.select:
 | 
			
		||||
            self._add_select_field(field, var_name, required, label, help_text)
 | 
			
		||||
 | 
			
		||||
        if required and default is not None:
 | 
			
		||||
            self.fields[var_name].default = default
 | 
			
		||||
 | 
			
		||||
    def _add_select_field(self, field, var_name, required, label, help_text):
 | 
			
		||||
        extra_args = field.get('extra_args', {})
 | 
			
		||||
        options = extra_args.get('options', '').splitlines()
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            options_data = {option.split(':')[0]: option.split(':')[1] for option in options}
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            raise ValidationError(f"Invalid options format: {str(e)}")
 | 
			
		||||
 | 
			
		||||
        DynamicFieldType = models.TextChoices('DynamicFieldType', options_data)
 | 
			
		||||
        self.fields[var_name] = LabeledChoiceField(
 | 
			
		||||
            choices=DynamicFieldType.choices, required=required, label=label,
 | 
			
		||||
            help_text=help_text
 | 
			
		||||
        )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue