每次输入新值“ sku”(不是创建新条目)时,我都需要更新我的表,但是只有在选择的“客户端”相同的情况下,它才必须发生。如果“客户端”不同,则模型应添加一个具有相同“ sku”但具有不同“客户端”的新对象。
一个StackOverflow用户给了我解决方案:
class ProductList(models.Model):
id_new = models.IntegerField(primary_key=True)
sku = models.CharField(primary_key=False, max_length=200)
client = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
name = models.CharField(max_length=256)
description = models.CharField(max_length=1000)
storage = models.CharField(max_length=256)
cost_price = models.CharField(max_length=256)
sell_price = models.CharField(max_length=256)
ncm = models.CharField(max_length=256)
inventory = models.IntegerField(null=True)
class Meta:
unique_together = (('sku', 'client'),)
def save(self, *args, **kwargs):
if self.pk:
current_instance = self.__class__.objects.get(pk=self.pk)
if current_instance.client != self.client:
self.pk = None
return super(ProductList, self).save(*args, **kwargs)
添加了保存功能后,问题解决了。但是,如果我尝试更新现有表,则文件中的每个字段都会遇到以下问题:
Line number: 1 - get() returned more than one ProductList -- it returned 2!
345, Teste 1, Descrição 1, 87654, 59,99, 180, 65, 884, 25
Traceback (most recent call last):
File "/home/checkstore/.local/lib/python3.6/site-packages/import_export/resources.py", line 453, in import_row
instance, new = self.get_or_init_instance(instance_loader, row)
File "/home/checkstore/.local/lib/python3.6/site-packages/import_export/resources.py", line 267, in get_or_init_instance
instance = self.get_instance(instance_loader, row)
File "/home/checkstore/.local/lib/python3.6/site-packages/import_export/resources.py", line 261, in get_instance
return instance_loader.get_instance(row)
File "/home/checkstore/.local/lib/python3.6/site-packages/import_export/instance_loaders.py", line 33, in get_instance
return self.get_queryset().get(**params)
File "/home/checkstore/.local/lib/python3.6/site-packages/django/db/models/query.py", line 403, in get
(self.model._meta.object_name, num)
Clientes.models.ProductList.MultipleObjectsReturned: get() returned more than one ProductList -- it returned 2!
我的admin.py文件显示如下:
from django.contrib import admin
from .forms import FaturaForm, ConfirmImportForm
from .models import (Token,
Sell,
LogisticCost,
IncomeCost,
FinalPayment,
CustomerServiceCost,
Fatura,
ProductList)
from import_export.admin import ImportExportModelAdmin, ImportMixin
from .resources import ProductListResource
from django.contrib.auth.models import User
try:
from django.utils.encoding import force_text
except ImportError:
from django.utils.encoding import force_unicode as force_text
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.utils.translation import ugettext_lazy as _
class ProductAdminImport(ImportExportModelAdmin, ImportMixin):
resource_class = ProductListResource
list_display = ('sku', 'client', 'name', 'description', 'storage', 'cost_price', 'sell_price', 'ncm', 'inventory')
list_filter = ['client']
def process_import(self, request, *args, **kwargs):
"""
Perform the actual import action (after the user has confirmed the import)
"""
if not self.has_import_permission(request):
raise PermissionDenied
confirm_form = ConfirmImportForm(request.POST)
if confirm_form.is_valid():
import_formats = self.get_import_formats()
input_format = import_formats[
int(confirm_form.cleaned_data['input_format'])
]()
tmp_storage = self.get_tmp_storage_class()(name=confirm_form.cleaned_data['import_file_name'])
data = tmp_storage.read(input_format.get_read_mode())
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)
for i in User.objects.all():
if i.username == str(request.POST['original_file_name'].split('.')[0]):
dataset.append_col([i.id] * dataset.height, header='client')
result = self.process_dataset(dataset, confirm_form, request, *args, **kwargs)
tmp_storage.remove()
return self.process_result(result, request)
def import_action(self, request, *args, **kwargs):
'''
Perform a dry_run of the import to make sure the import will not
result in errors. If there where no error, save the user
uploaded file to a local temp file that will be used by
'process_import' for the actual import.
'''
if not self.has_import_permission(request):
raise PermissionDenied
resource = self.get_import_resource_class()(**self.get_import_resource_kwargs(request, *args, **kwargs))
context = self.get_import_context_data()
import_formats = self.get_import_formats()
form_type = self.get_import_form()
form = form_type(import_formats,
request.POST or None,
request.FILES or None)
if request.POST and form.is_valid():
input_format = import_formats[
int(form.cleaned_data['input_format'])
]()
import_file = form.cleaned_data['import_file']
# first always write the uploaded file to disk as it may be a
# memory file or else based on settings upload handlers
tmp_storage = self.write_to_tmp_storage(import_file, input_format)
# then read the file, using the proper format-specific mode
# warning, big files may exceed memory
try:
data = tmp_storage.read(input_format.get_read_mode())
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)
except UnicodeDecodeError as e:
return HttpResponse(_(u"<h1>Imported file has a wrong encoding: %s</h1>" % e))
except Exception as e:
return HttpResponse(
_(u"<h1>%s encountered while trying to read file: %s</h1>" % (type(e).__name__, import_file.name)))
# if str(request.user.username) == str(import_file.name.split('.')[0]):
for i in User.objects.all():
csv_client_name = str(import_file.name.split('.')[0])
if i.username == csv_client_name:
dataset.append_col([i.id] * dataset.height, header='client')
result = resource.import_data(dataset, dry_run=True,
raise_errors=False,
file_name=import_file.name,
user=request.user)
context['result'] = result
if not result.has_errors():
context['confirm_form'] = ConfirmImportForm(initial={
'import_file_name': tmp_storage.name,
'original_file_name': import_file.name,
'input_format': form.cleaned_data['input_format'],
})
context.update(self.admin_site.each_context(request))
context['title'] = _("Import")
context['form'] = form
context['opts'] = self.model._meta
context['fields'] = [f.column_name for f in resource.get_user_visible_fields()]
request.current_app = self.admin_site.name
return TemplateResponse(request, [self.import_template_name],
context)
class FaturaModel(admin.ModelAdmin):
form = FaturaForm
list_filter = ['cliente', 'pago']
list_display = ('cliente',
'id',
'dia',
'numero_da_fatura',
'mes',
'ano',
'valor',
'pago')
class SellsAdmin(admin.ModelAdmin):
list_filter = ['client']
list_display = ['client', 'date']
admin.site.register(Token)
admin.site.register(Sell, SellsAdmin)
admin.site.register(LogisticCost)
admin.site.register(IncomeCost)
admin.site.register(FinalPayment)
admin.site.register(CustomerServiceCost)
admin.site.register(Fatura, FaturaModel)
admin.site.register(ProductList, ProductAdminImport)
答案 0 :(得分:1)
据我所知,您需要更新ProductListResource
。您可以尝试这样:
class ProductListResource(resources.ModelResource):
class Meta:
model = ProductList
import_id_fields = ('sku','client',) # <-- Add multiple id fields
fields = (sku', 'client', 'name', 'description', 'storage',...) # other fields
顺便说一句,我认为您无需重写save
方法即可生成重复项。如果将sku
和client
用作多个标识,当 django-import-export 看到一个{{1}的不同client
时,将始终创建新实例。 }。
答案 1 :(得分:0)
在save()
函数中。
if current_instance.client != self.client:
self.pk = None
更改为
if current_instance.client != self.client:
self.id_new = None
如果self.pk
为您提供了self.id_new
的值,则分配给self.pk
的值不适用于self.id_new
。确实,实例的值会立即更改,但是当您调用save()
函数时,该值不适用于数据库。
所以我认为这会导致意外的重复值。
答案 2 :(得分:0)
我找到的解决方案如下:
在软件包文件instance_loaders.py
中,我修改了该函数:
def get_queryset(self):
return return self.resource._meta.model.objects.all()
收件人:
def get_queryset(self):
return self.resource._meta.model.objects.filter(client=self.dataset._data[0]._row[-1]).all()
那解决了我所有的问题。