django-import-export 分配当前用户

问题描述 投票:0回答:3

尝试在创建实例时分配added_by用户并想要创建引用当前实例的另一个模型实例

views.py

class ImportFarmersView(APIView):
    parser_classes = (MultiPartParser,)

    def post(self,request,org_slug=None,format=None,*args,**kwargs):
        serializer=TmpFileUploadSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(data=serializer.errors,status=status.HTTP_400_BAD_REQUEST)
        entries=serializer.validated_data['file']

        profile_resource=ProfileResource()
        dataset=Dataset()
        imported_data = dataset.load(open(entries.temporary_file_path(),'rb').read(),'xls')
        result = profile_resource.import_data(dataset, dry_run=True)  # Test the data import

        if result.has_errors():
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
        profile_resource.import_data(dataset, dry_run=False)  # Actually import now

        return Response(status=status.HTTP_202_ACCEPTED)

资源.py

class ProfileResource(resources.ModelResource):
    created_at=fields.Field(readonly=True)
    updated_at=fields.Field(readonly=True)
    class Meta:
        model=Profile
        skip_unchange=True
        report_skipped=False
        import_id_fields=('slug','email')

提前致谢

django django-rest-framework django-import-export
3个回答
5
投票

我使用了 @Jagu 提出的

before_import_row
答案的替代解决方案。

我不想使用

before_import_row
解决方案的原因是因为它迫使我为资源创建一个字段属性。此外,在管理页面的导入过程中,当导入器显示:
This importer will import the following fields: field1, field2, autofield1, autofield2
时,我的用户可能会对导入器所需的字段感到困惑。相反,我宁愿说:
This importer will import the following fields: field1, field2

让我们继续解决方案。

假设我有这个型号:

class LotNumber(models.Model):
    lot_number = models.CharField(
        max_length=16,
        primary_key=True
    )
    is_active = models.BooleanField(
        default=True
    )
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        editable=False,
        related_name='+',
        on_delete=models.SET_NULL
    )

我将指定

created_by
属性作为 auto-populated 字段。

现在我的资源类如下所示:

class LotNumberResource(resources.ModelResource):

    class Meta:
        model = LotNumber
        skip_unchanged = True
        report_skipped = False
        fields = (
            'lot_number',
            'is_active',
        )

    def after_import_instance(self, instance, new, **kwargs):
        instance.created_by = kwargs['user']

如您所见,在我的

Meta
块中,我只需指定
lot_number
is_active
。然而,我选择重写的方法是
after_import_instance
。起初我尝试使用
before_import_row
但修改行并没有自动填充
created_by
字段。深入研究源代码后,我注意到方法
get_or_init_instance
before_import_row
方法之后被调用(参见源代码 here),该方法使用我定义的资源类获取模型实例(参见源代码 here )。因此,如果资源类未在
fields
属性中列出自动填充字段,则实例将永远不会获取该字段。


2
投票

您可以在 resources.ModelResource 上的 before_import_row 挂钩中访问当前的 django 用户。 **kwarg 中有一个“用户”。

所以在你的情况下它看起来像这样

class ProfileResource(resources.ModelResource):
    ...
    def before_import_row(self, row, **kwargs):
        row['added_by'] = kwargs['user'].id

如果你在其中放置一个断点()并查看 kwargs,你会看到类似这样的东西(请注意,用户记录被包装在 SimpleLazyObject 中):

-> row['added_by'] = kwargs['user'].id
(Pdb) kwargs
{'file_name': 'ImportDatasetWorking.csv', 'user': <SimpleLazyObject: <User: 
Kumar>>}

0
投票

我也能够解决类似的问题。这就是我修复它的方法

模型.py

class Resource(BaseModel):
    category = models.CharField(max_length=100)
    name = models.CharField(max_length=100)
    resource_type = models.CharField(max_length=100, null=True, blank=True) 
    description = models.TextField()
    url = models.URLField()
    document = models.FileField(upload_to="images/resource")
    created_by = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        ordering = ('-date_created',)
        verbose_name = "Resource Library"
        verbose_name_plural = "Resource Libraries"

    def __str__(self):
        return self.name

资源.py

from .models import Resource
from import_export.resources import ModelResource

class ResourceResource(ModelResource):

    class Meta:
        model = Resource
        skip_unchanged = True
        report_skipped = False

    def before_import_row(self, row, **kwargs):
        row['created_by'] = kwargs['user'].id

管理员.py

from django.contrib import admin
from apps.resourcelibraries.models import Resource
from import_export.admin import ImportExportModelAdmin
from .resources import ResourceResource


class AdminResource(ImportExportModelAdmin):
    resource_class = ResourceResource
    list_display = ('category', 'name', 'resource_type' , 'created_by', 'url', 'date_created')

admin.site.register(Resource, AdminResource)

© www.soinside.com 2019 - 2024. All rights reserved.