代码之家  ›  专栏  ›  技术社区  ›  markwalker_

在导入时保存实例之前对其进行修改

  •  0
  • markwalker_  · 技术社区  · 2 年前

    我正在为具有 ForeignKey 关系,并且我在模型上有一个额外的字段,如果提供的值是相关表的无效ID,我想在其中存储该值。所以如果 Passport 对象在导入的文件中不存在UUID,文件中的值将添加到 invalid_passport 领域这样,可以通过django admin查看它,并可能在导入过程完成后使用它。

    这里讨论的ID是UUID,因此很可能有人会提供一些无效数据。

    class Result(models.Model):
    
        id = models.UUIDField(
            primary_key=True,
            default=uuid.uuid4,
            editable=False
        )
        passport = models.ForeignKey(
            to='results.Passport',
            null=True,
            blank=True,
            on_delete=models.SET_NULL
        )
        invalid_passport = models.CharField(
            max_length=255,
            blank=True,
            null=True,
            help_text=_("An invalid passport number")
        )
    

    导入文件将包含 passport 列,但我想将提供的值保存到 无效的\u passport 如果不匹配 护照 实例。

    我的资源如下所示;

    class ResultResource(resources.ModelResource):
        """ Integrate django-import-export with the Result model """
        passport = fields.Field(
            column_name='passport',
            attribute='passport',
            widget=ForeignKeyWidget(Passport, 'id')
        )
    
        class Meta:
            instance_loader_class = CachedInstanceLoader
            model = Result
            fields = (
                'id',
                'passport',
                'invalid_passport'
            )
    
        def init_instance(self, row=None):
            """ Initializes a new Django model. """
            instance = self._meta.model()
            if not instance.passport:
                instance.invalid_passport = row['passport']
            return instance
    
        def before_save_instance(self, instance, using_transactions, dry_run):
            """ Sets the verified flags where there is a passport match. """
            if instance.passport:
                instance.verified = True
                instance.verified_by = self.import_job.author
                instance.invalid_passport = None
            else:
                pass
    

    因此,在创建实例时 护照 ID存储在 无效的\u passport . 我的理论是 before_save_instance 我可以检测到 护照 存在,但 if 正在中执行 \u save\u实例之前 .

    这是错误的方法吗?

    0 回复  |  直到 2 年前
        1
  •  1
  •   Matthew Hegarty Edwin Lunando    2 年前

    一个问题是,如果护照不存在 ForeignKeyWidget 将引发 DoesNotExist 异常,将不会导入您的行,并将标记为错误。但是,这对您来说可能没问题,因为您可能只对记录没有错误的行感兴趣。

    所以除非我错过了什么,否则我不知道怎么做 before_save_instance() 将被调用,因为 实干家 首先引发异常,这意味着不会调用任何保存逻辑。

    如果你看 this line 您可以看到异常正在添加到 Error 对象,然后存储在导入的结果中。这似乎是记录无效护照ID的一个好选择。事实上 错误 对象将记录异常( 实干家 )和行,因此您已经有了失败行的记录,而无需任何自定义。您可以覆盖 Result 或者 错误 对象来对此进行更多控制。

    另一个想法可能是覆盖 before_import() 进行一些预处理。在里面 \u import()之前 ,您可以将所有现有的passport UUID加载到内存中,然后扫描数据集以删除任何不存在的行。如果您有大桌子,这可能不实用。

    但是,您确实说过要在模型上记录丢失的UUID,因此可以引入自定义 ForeignKeyWidget 不引发 实干家 异常,并可能引发 ValidationError 相反在这种情况下,错误将存储在 import_validation_errors . 然后你可以覆盖 validate_instance() 将错误读回并存储在模型上。

        2
  •  0
  •   Abdelhamed Abdin    2 年前

    好的,我想我有一个解决方案,也许它的顺序并不完美,但我会告诉你什么是fit工具,它在这些任务中帮助了我很多。所以我认为 信号 是成功完成此任务的最佳方法

    因此,我将告诉您我在伪代码中得到的步骤,您可以根据您的想法修改它们:

    • 您将使用pre\u save获取已在请求中发布的数据
    • 在将应用信号的函数中,打开CSV文件
    • 获取UUID并在CSV文件中搜索它
    • 比较来自CSV文件和UUID的数据
    • 如果数据与任何UUID或任何要比较的字段不匹配,请将该UUID保存在invalid\u passport中
    • 否则,不要保存它,并将您的响应作为成功视图返回

    您可以在此处阅读有关pre\u save和signals的更多信息: https://docs.djangoproject.com/en/4.0/ref/signals/

    提示:
    打开文件并从文件中获取数据的最快方法是在pandas中使用dataframe如果您熟悉pandas,那么您将比在Django中使用打开的文件更快地完成此任务,并且在搜索中使用强大的性能,因为在pandas中,您不需要使用循环来搜索与python中的正常循环相反的大量数据

    推荐文章