簡體   English   中英

如何在 django-import-export 中導入 django-taggit 標簽

[英]How to import django-taggit tag in django-import-export

我無法使用 Django-import-export 導入 Django-taggit 標簽。

這個錯誤是在輸入值時。

Line number: 1 - invalid literal for int() with base 10: 'def'

此外,此錯誤是當值為空時。

Line number: 2 - Cannot add <QuerySet []> (<class 'django.db.models.query.QuerySet'>). Expected <class 'django.db.models.base.ModelBase'> or str.

我也在這個問題中發布了問題

xlsx 表也有一個 id 列。

在此處輸入圖片說明

模型.py

from django.db import models
from django.urls import reverse
from taggit.managers import TaggableManager

class KnowHow(models.Model):    

    author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    text = models.TextField(blank=True)
    file = models.FileField(blank=True,upload_to='explicit_knowhows')
    free_tags = TaggableManager(blank=True)

    def __str__(self):
        return self.title

管理文件

from django.contrib import admin
from import_export import resources
from import_export import fields
from import_export.admin import ImportExportModelAdmin

from .models import KnowHow
# Register your models here.

class KnowHowResource(resources.ModelResource):

    class Meta:
        model = KnowHow
        import_id_fields = ['id']

@admin.register(KnowHow)
class knowHowAdmin(ImportExportModelAdmin):
    resource_class = KnowHowResource

我的解決方案:

自定義小部件:

from import_export import fields
from import_export import widgets
from taggit.forms import TagField
from taggit.models import Tag

class TagWidget(widgets.ManyToManyWidget):
    def render(self, value, obj=None):
        return self.separator.join(
            [obj.name for obj in value.all()]
        )

    def clean(self, value, row=None, *args, **kwargs):
        values = TagField().clean(value)
        return [
            Tag.objects.get_or_create(name=tag)[0]
            for tag in values
        ]

然后我們還必須覆蓋字段:

class TagFieldImport(fields.Field):

    def save(self, obj, data, is_m2m=False):
        # This method is overridden because originally code
        # getattr(obj, attrs[-1]).set(cleaned, clean=True) doesn't unpack cleaned value
        if not self.readonly:
            attrs = self.attribute.split('__')
            for attr in attrs[:-1]:
                obj = getattr(obj, attr, None)
            cleaned = self.clean(data)
            if cleaned is not None or self.saves_null_values:
                if not is_m2m:
                    setattr(obj, attrs[-1], cleaned)
                else:
                    # Change only here
                    getattr(obj, attrs[-1]).set(*cleaned, clean=True)

然后像這樣在資源中使用:

    tags = cure_widgets.TagFieldImport(
        attribute="tags",
        column_name="tags",
        widget=cure_widgets.TagWidget(Tag, separator=", ")
    )

我使用的另一種可能的解決方案/解決方法。

定義一個輔助模型文本字段來存儲逗號分隔的標簽列表。 我們稱之為“tags_char”。 然后覆蓋模型的 save 方法,將逗號分隔的列表轉換為 Tag 對象。

# models.py
from django.db import models
from taggit.managers import TaggableManager

class Book(models.Model):
    
    tags_char = models.TextField(blank=True)
    tags = TaggableManager(blank=True)
    
    def save(self, *args, **kwargs):
        if ',' in self.tags_char and self.pk:
            for tag in self.tags_char.split(','):
                self.tags.add(tag)
        super(Book, self).save(*args, **kwargs)

最后一步是調整ModelResource。 我們從導入中排除標簽,而是從文件中導入到 tags_char。 知道一旦保存對象,轉換就會發生。

#admin.py
class BookResource(resources.ModelResource):
    class Meta:
        model = Book
        exclude = ('id', 'tags') 

不幸的是,這種變通方法存在一個問題。 由於 django 導入導出的工作方式,在為對象分配 id (pk) 之前調用 save() 方法。 如果 id 不存在,則無法添加標簽。 這就是檢查save方法中是否存在self.pk的原因。 if ',' in self.tags_char and self.pk

有三種替代方法可以解決這個問題。

  1. 如果您要補充數據或在將其發布到網站之前對其進行審查。 您需要手動重新保存它們 => 問題已解決(我就是這種情況)
  2. 只需導入文件兩次。 第二次圍繞 id 的遺囑存在。
  3. 在要導入的文件中提供一個 ID。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM