在创建实例时尝试分配add_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)
resources.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')
预先感谢
答案 0 :(得分:0)
您可以在resources.ModelResource上的before_import_row钩子中访问当前的django用户。 ** kwarg中有一个“用户”。
所以在您的情况下,它看起来像
class ProfileResource(resources.ModelResource):
...
def before_import_row(self, row, **kwargs):
row['added_by'] = kwargs['user'].id
如果在其中放置一个breakpoint()并查看kwarg,您将看到类似以下内容(请注意,用户记录包装在SimpleLazyObject中):
-> row['added_by'] = kwargs['user'].id
(Pdb) kwargs
{'file_name': 'ImportDatasetWorking.csv', 'user': <SimpleLazyObject: <User:
Kumar>>}
答案 1 :(得分:0)
我对@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
属性指定为自动填充字段。
现在这是我的资源类:
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
属性中列出自动填充的字段,则实例将永远不会获取该字段。