ModelResource未使用的文件中的Django导入-导出访问字段

时间:2019-01-09 11:23:22

标签: python django django-2.0 django-import-export

原始问题发布在这里:https://github.com/django-import-export/django-import-export/issues/886

大家好,

我有一个xslx文档,其中包含以下列:

类别|场地|事件问题回答|客户|动作

类别,地点,事件和客户是外键。如果它们不存在,则应该创建它们,以便我创建自定义的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

我理解为什么会发生这种情况,但是我无法弄清楚如何访问另一个列的值并使用该值为其他外键创建关系。

创建模型场所和事件时,它们需要客户端父模型。由于我的问题没有这种关系,因此需要创建它,以便可以创建我的其他模型(事件和地点)。

谢谢!

1 个答案:

答案 0 :(得分:0)

我终于解决了一切。这是我的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)