首页 > 解决方案 > Django rest框架默认值随机标识符

问题描述

当我尝试在 MongoEngine 中保存 DynamicDocument 时,我正在尝试调试一个奇怪的行为。文档类声明如下:

class Command(DynamicDocument):
    meta = {
        'collection': 'executor_data_commands'
    }

    name = StringField()
    args = DynamicField()
    issued_at = LongField(default=time.time())
    sync_with_kafka = BooleanField(default=False)
    correlation_id = StringField(
        default=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
    )
    commands_output = DynamicField(default=None)

    @classmethod
    def post_save(cls, sender, document, **kwargs):
        """
        Send data to Kafka executor data topic after a new instance has been saved
        :param sender: the sender who emitted the signal
        :param document: the saved instance
        """
        if kwargs['created']:
            CommandHandler(document).send_command()



class CommandHandler:
    """
    Command handler class
    """

    def __init__(self, command_instance):
        self.command_instance = command_instance

    def send_command(self):
        """
        Send command to Kafka queue and save the response in the
        local database
        :return: True if message is published over Kafka channel
        False otherwise
        """
        headers = {
            "Content-Type": "application/vnd.kafka.json.v2+json",
            "Accept": "application/vnd.kafka.v2+json"
        }

        logger_kafka_handlers.info(
            "Got new command: %s - %s" % (self.command_instance.name, self.command_instance.args))

        args = self.command_instance.args
        if 'machine_identifier' in args:
            args['machine_identifier'] = MACHINE_MAPPING.get(args['machine_identifier'], args['machine_identifier'])

        response = requests.post(
            KAFKA_BROKER_EXECUTOR_COMMANDS_IN['host'],
            json={"records": [{"value": {
                "name": self.command_instance.name,
                "args": args,
                "correlation_id": self.command_instance.correlation_id,
                "issued_ts": time.time()
            }}]},
            headers=headers,
            auth=(KAFKA_BROKER_EXECUTOR_COMMANDS_IN['user'], KAFKA_BROKER_EXECUTOR_COMMANDS_IN['password'])

        )

        self.command_instance.sync_with_kafka = True if response.status_code == 200 else False
        self.command_instance.save()
        logger_kafka_handlers.info(
        "Handled new command; Name: %s - Args: %s - Sync with Kafka: %s; CorrelationId: %s" % (
            self.command_instance.name, self.command_instance.args, self.command_instance.sync_with_kafka,
            self.command_instance.correlation_id))

所以我希望创建的文档将有一个 10 个字母的随机相关ID并传递给post_save处理程序,该处理程序基本上执行 HTTP 请求并记录实例字段。

问题与correlation_id字段有关:似乎分配给每个已保存实例的默认值等于数据库中保存的另一个实例。

我排除了后台更新查询以及一些变量重新分配,因为在send_command方法的最后一行记录实例字段时,该问题清晰可见。

想法?

谢谢,脸书

标签: djangodjango-rest-frameworkmongoengine

解决方案


问题在于你对default价值的理解。

我不确定 mongo DynamicDocument,但我认为它与普通模型的行为相同。

因此,从文档中:

字段的默认值。这可以是一个值或可调用对象。如果可调用,则每次创建新对象时都会调用它。

在您的情况下,它是不可调用的,因此在创建模型类时只调用一次。

您需要使其可调用,因此将实现移至函数:

def generate_random_corr():
    return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))

并像这样在模型类中使用它:

 correlation_id = StringField(default=generate_random_corr)

同样适用于其他领域:

issued_at = LongField(default=time.time())

所有对象的时间都相同。


推荐阅读