Django import export get() возвращает более одного значения
У меня есть небольшое приложение Django с cities_light
, smart_selects
и import_export
. Я могу правильно экспортировать данные из админки в файлы csv с помощью resources
и ForeignKeyWidget
из import_export
. Однако с импортом что-то не так, и я не уверен, как это исправить. При попытке импорта через сайт администратора из того же экспортированного csv-файла я получаю jobs.models.City.MultipleObjectsReturned: get() returned more than one City -- it returned 2!
.
Этот вопрос похож на этот, но я все еще не понимаю, что не так. Буду очень признателен, если ответы будут содержать ссылки на документацию, объясняющую, что я делаю неправильно, поскольку я прошел через ReadTheDocs, но не смог найти свою ошибку.
Спасибо.
models.py
class Country(AbstractCountry):
pass
connect_default_signals(Country)
class Region(AbstractRegion):
def __str__(self):
return self.name
country = models.ForeignKey(Country, on_delete=models.PROTECT)
connect_default_signals(Region)
class SubRegion(AbstractSubRegion):
pass
connect_default_signals(SubRegion)
class City(AbstractCity):
def __str__(self):
return self.name
region = models.ForeignKey(Region, on_delete=models.PROTECT)
connect_default_signals(City)
class JobPost(models.Model):
title = models.CharField(max_length=100)
company = models.CharField(max_length=100)
urlCompany = models.URLField(blank=True)
urlApplication = models.URLField(blank=True)
contactEmail = models.EmailField(max_length=100, blank=True)
jobType = models.CharField(max_length=100, blank=True)
country = models.ForeignKey(Country, on_delete=models.PROTECT, blank=True)
region = ChainedForeignKey(
Region,
chained_field="country",
chained_model_field="country",
show_all=False,
auto_choose=True,
sort=True,
blank=True
)
city = ChainedForeignKey(
City,
chained_field="region",
chained_model_field="region",
show_all=False,
auto_choose=True,
sort=True,
blank=True
)
createdAt = models.DateTimeField(auto_now_add=True)
remainingDays = models.IntegerField(default=90, blank=False)
valid = models.BooleanField(default=True)
visible = models.BooleanField(default=True)
description = models.TextField()
admin.py
from .models import JobPost, Country, Region, City
class JobPostResource(resources.ModelResource):
country = fields.Field(
column_name='country',
attribute='country',
widget=ForeignKeyWidget(Country, 'name'))
region = fields.Field(
column_name='region',
attribute='region',
widget=ForeignKeyWidget(Region, 'name'))
city = fields.Field(
column_name='city',
attribute='city',
widget=ForeignKeyWidget(City, 'name'))
class Meta:
model = JobPost
export_order = ('id', 'title', 'company', 'urlCompany', 'urlApplication', 'contactEmail',
'jobType', 'country', 'region', 'city', 'createdAt', 'remainingDays',
'valid', 'visible', 'description')
fields = ('id', 'title', 'company', 'urlCompany', 'urlApplication', 'contactEmail',
'jobType', 'country', 'region', 'city', 'createdAt', 'remainingDays',
'valid', 'visible', 'description')
class JobPostAdmin(SummernoteModelAdmin, ImportExportModelAdmin):
summernote_fields = ('description', )
resource_class = JobPostResource
admin.site.register(JobPost, JobPostAdmin)
csv
id,title,company,urlCompany,urlApplication,contactEmail,jobType,country,region,city,createdAt,remainingDays,valid,visible,description
888,xxx,asfasdf,,,,,United States,Texas,Austin,2022-06-10 19:27:36,90,1,1,<p>asdfasdf</p>
Вернулся несколько месяцев спустя, чтобы ответить на свой собственный вопрос...
В исходном коде widgets.py
, в коде import_export
, когда я искал get_queryset
, чтобы попытаться понять немного лучше, что происходит, я нашел этот комментарий:
Overwrite this method if you want to limit the pool of objects from
which the related object is retrieved.
:param value: The field's value in the datasource.
:param row: The datasource's current row.
As an example; if you'd like to have ForeignKeyWidget look up a Person
by their pre- **and** lastname column, you could subclass the widget
like so::
class FullNameForeignKeyWidget(ForeignKeyWidget):
def get_queryset(self, value, row, *args, **kwargs):
return self.model.objects.filter(
first_name__iexact=row["first_name"],
last_name__iexact=row["last_name"]
)
Именно это я и сделал, я переписал метод. Например, теперь у меня есть:
class RegionCountryForeignKeyWidget(ForeignKeyWidget):
def get_queryset(self, value, row, *args, **kwargs):
return self.model.objects.filter(
name__iexact=row["region"],
country__name__iexact=row["country"]
)
и это работает.