Поля доступа к Django-import-export в файле, не используемые ModelResource
Оригинальный вопрос был размещен здесь: https://github.com/django-import-export/django-import-export/issues/886
Здравствуйте все,
У меня есть документ xslx со следующими столбцами:
категория | место проведения | событие | вопрос | ответ | клиент | действие
Категория, место проведения, событие и клиент - ForeignKeys. Если они не существуют, они должны быть созданы, поэтому я создал пользовательские ForeignKeyWidgets:
class ForeignKeyWidgetWithCreation(ForeignKeyWidget):
def __init__(
self,
model,
field='pk',
create=False,
*args, **kwargs):
self.model = model
self.field = field
self.create = create
# super(ForeignKeyWidgetWithCreation, self).__init__(*args, **kwargs)
def clean(self, value, row=None, *args, **kwargs):
val = super(ForeignKeyWidgetWithCreation, self).clean(value)
if self.create:
instance, new = self.model.objects.get_or_create(**{
self.field: val
})
val = getattr(instance, self.field)
return self.model.objects.get(**{self.field: val}) if val else None
# Event Widget
class EventWidget(ForeignKeyWidget):
def __init__(
self,
model,
field='pk',
create=False,
*args, **kwargs):
self.model = model
self.field = field
self.create = create
# super(ForeignKeyWidgetWithCreation, self).__init__(*args, **kwargs)
def clean(self, value, row=None, *args, **kwargs):
val = super(ForeignKeyWidgetWithCreation, self).clean(value)
if self.create:
instance, new = self.model.objects.get_or_create(**{
self.field: val
})
val = getattr(instance, self.field)
return self.model.objects.get(**{self.field: val}) if val else None
# CLIENT WIDGET
class ClientWidget(ForeignKeyWidget):
def __init__(self, model, field='client', *args, **kwargs):
self.model = Client
self.field = field
def clean(self, value, row=None, *args, **kwargs):
val = super(ClientWidget, self).clean(value)
if val:
client = Client.objects.get_or_create(name=val)
return client
# return self.get_queryset(value, row, *args, **kwargs).get(**{self.field: val})
else:
return None
# VENUE WIDGET
class VenueWidget(ForeignKeyWidget):
def __init__(self, model, field='pk', *args, **kwargs):
self.model = model
self.field = field
self.other_widget = ClientWidget(model=Client)
def clean(self, value, row=None, *args, **kwargs):
client = self.other_widget.clean(row['client'], row)
print(client)
return self.model.objects.get_or_create(venue=value, client=client)
Мой модельный ресурс выглядит следующим образом:
class QuestionResource(resources.ModelResource):
category = fields.Field(
column_name='category',
attribute='category',
widget=ForeignKeyWidgetWithCreation(Category, 'category')
)
venue = fields.Field(
column_name='venue',
attribute='venue',
widget=VenueWidget(Venue, 'venue')
)
event = fields.Field(
column_name='event',
attribute='event',
widget=ForeignKeyWidgetWithCreation(Event, 'event')
)
client = fields.Field(
column_name='client',
attribute='client',
widget=ClientWidget(Client, 'name')
)
class Meta:
model = Question
fields = ['id', 'question', 'venue', 'category', 'answer', 'event', 'client']
Моя модель НЕ имеет отношения к полю клиента, но я хочу создать нового Клиента, основываясь на том, существует он или нет.
В настоящее время, когда я загружаю файл xlsx, я получаю следующую ошибку:
django.core.exceptions.FieldError: Cannot resolve keyword 'client' into field. Choices are: created, id, modified, name, profile, question, update, venue
Я понимаю, почему это происходит, но я не могу понять, как получить доступ к значению другого столбца и использовать его для создания отношения для других моих внешних ключей.
Когда создаются модели Venue и Event, им нужна родительская модель Client. Поскольку мой вопрос не имеет такого отношения, мне нужно создать его, чтобы можно было создавать другие мои модели (Event & Venue).
Заранее спасибо!
1 ответ
Я решил все это в конце концов. Вот мой admin.py. Я надеюсь, что это помогает!
from import_export.admin import ImportExportModelAdmin
from django.contrib import admin
from .models import Question, Category
from events.models import Event
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget, DateTimeWidget
from django_summernote.admin import SummernoteModelAdmin
from clients.models import Client
from venues.models import Venue
# EVENT WIDGET
class EventWidget(ForeignKeyWidget):
def __init__(
self,
model,
field='pk',
create=False,
*args, **kwargs):
self.model = model
self.field = field
self.create = create
def clean(self, value, row=None, *args, **kwargs):
venue_row_value = row["venue"]
venue = Venue.objects.filter(venue__iexact=venue_row_value).first()
obj, created = self.model.objects.get_or_create(event=value, venue=venue)
return obj
# CLIENT WIDGET
class ClientWidget(ForeignKeyWidget):
def __init__(
self,
model,
field='pk',
create=False,
*args, **kwargs):
self.model = model
self.field = field
self.create = create
def clean(self, value, row=None, *args, **kwargs):
obj, created = self.model.objects.get_or_create(name=value)
return obj
# VENUE WIDGET
class VenueWidget(ForeignKeyWidget):
def clean(self, value, row=None, *args, **kwargs):
client = Client.objects.get(name__iexact=row["client"])
obj, created = self.model.objects.get_or_create(venue=value, client=client)
return obj
class CategoryWidget(ForeignKeyWidget):
def clean(self, value, row=None, *args, **kwargs):
obj, created = self.model.objects.get_or_create(category=value)
return obj
class QuestionResource(resources.ModelResource):
client = fields.Field(
column_name='client',
attribute='client',
widget=ClientWidget(Client, 'name')
)
category = fields.Field(
column_name='category',
attribute='category',
widget=CategoryWidget(Category, 'category')
)
venue = fields.Field(
column_name='venue',
attribute='venue',
widget=VenueWidget(Venue, 'venue')
)
event = fields.Field(
column_name='event',
attribute='event',
widget=EventWidget(Event, 'event')
)
class Meta:
model = Question
fields = ['id', 'client', 'question', 'venue', 'category', 'answer', 'event',]
@admin.register(Question)
class QuestionAdmin(ImportExportModelAdmin, SummernoteModelAdmin):
exclude = ('verified_by',)
resource_class = QuestionResource
summernote_fields = ('answer', 'info')
# Displays the columns in the admin page overview of questions
list_display = ('question', 'event', 'category', 'verified', 'verified_by',)
# Immediately edit the model by clicking on the question, category or verified
list_display_links = ('question', 'event', 'category', 'verified')
# filtering in the adminpage:
list_filter = ('verified', 'event', 'category',)
def save_model(self, request, obj, form, change):
if obj.verified == True:
obj.verified_by = request.user
else:
obj.verified_by = None
super().save_model(request, obj, form, change)
admin.site.register(Category)