Example of import csv file - scieloorg/template-scms Wiki

Prerequisites:

To follow this example is necessary to have this model:

https://github.com/scieloorg/template-scms/wiki/Create-a-model-admin-on-Wagtail

Update the template-scms with the lastest version.

Create a CSV import model:

In the source_diretory django application change the file wagtail-hooks.py with this content:

from django.urls import path
from django.utils.translation import gettext as _

from wagtail.core import hooks
from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register, ModelAdminGroup)

from .models import SourceDirectory, SourceDirectoryFile
from .button_helper import SourceDirectoryHelper
from .views import validate, import_file


class SourceDirectoryAdmin(ModelAdmin):
    model = SourceDirectory
    menu_label = 'Source Directory'  # ditch this to use verbose_name_plural from model
    menu_icon = 'folder'  # change as required
    menu_order = 100  # will put in 3rd place (000 being 1st, 100 2nd)
    add_to_settings_menu = False  # or True to add your model to the Settings sub-menu
    exclude_from_explorer = False  # or True to exclude pages of this type from Wagtail's explorer view
    list_display = ('name', 'link', 'source_type')
    list_filter = ('source_type',)
    search_fields = ('name', 'source_type')
    list_export = ('name', 'link', 'source_type')
    export_filename = 'source_directory'


# Now you just need to register your customised ModelAdmin class with Wagtail
# modeladmin_register(SourceDirectoryAdmin)


class SourceDirectoryFileAdmin(ModelAdmin):
    model = SourceDirectoryFile
    button_helper_class = SourceDirectoryHelper
    menu_label = 'Source Directory Upload'  # ditch this to use verbose_name_plural from model
    menu_icon = 'folder'  # change as required
    menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
    add_to_settings_menu = False  # or True to add your model to the Settings sub-menu
    exclude_from_explorer = False  # or True to exclude pages of this type from Wagtail's explorer view
    list_display = ('attachment', 'line_count', 'is_valid')
    list_filter = ('is_valid',)
    search_fields = ('attachment',)


# Now you just need to register your customised ModelAdmin class with Wagtail
# modeladmin_register(SourceDirectoryFileAdmin)

class SourceDirectoryAdminGroup(ModelAdminGroup):
    menu_label = 'Source Directory '
    menu_icon = 'folder-open-inverse'  # change as required
    menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
    items = (SourceDirectoryAdmin, SourceDirectoryFileAdmin,)

modeladmin_register(SourceDirectoryAdminGroup)


@hooks.register('register_admin_urls')
def register_calendar_url():
    return [
        path('source_directory/sourcedirectoryfile/validate', validate, name='validate'),
        path('source_directory/sourcedirectoryfile/import_file', import_file, name='import_file'),
    ]

Create a new model called SourceDirectoryFile in models.py:

import os
from django.db import models
from django.utils.translation import gettext as _

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.documents.edit_handlers import DocumentChooserPanel
from wagtail.contrib.modeladmin.views import IndexView

from . import choices


class SourceDirectory(models.Model):
    name = models.CharField(_("Name"), max_length=255, null=False, blank=False)
    link = models.URLField("Link", null=False, blank=False)
    source_type = models.CharField(_("Source Type"), max_length=255,
                                   choices=choices.SOURCE_TYPE,
                                   null=True, blank=True)

    panels = [
        FieldPanel('name'),
        FieldPanel('link'),
        FieldPanel('source_type')
    ]


class SourceDirectoryFile(models.Model):

    attachment = models.ForeignKey(
        'wagtaildocs.Document',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    is_valid = models.BooleanField(_("É valido?"), default=False, blank=True, null=True)
    line_count = models.IntegerField(_("Quantidade de linhas"), default=0, blank=True, null=True)

    def filename(self):
        return os.path.basename(self.attachment.name)

    panels = [
        # FieldPanel('is_valid'),
        # FieldPanel('line_count'),
        DocumentChooserPanel('attachment')
    ]

Run the makemigration and migrate this this commands:


make django_makemigrations
make django_migrate 

Create a new file in source_diretory called chkcsvfmt.fmt with the content:

[Name]
data_required=True
type=String

[Link]
data_required=False
type=string

[Source_Type]
data_required=False
type=(primary|secondary|tertiary)

Create a new file to add to new buttons on admin interface, called button_helper.py:


from django.utils.translation import gettext as _
from wagtail.contrib.modeladmin.helpers import ButtonHelper

from django.urls import reverse

class SourceDirectoryHelper(ButtonHelper):

    # Define classes for our button, here we can set an icon for example
    validate_button_classnames = ["button-small", "icon",]
    import_button_classnames = ["button-small", "icon",]

    def validate_button(self, obj):
        # Define a label for our button
        text = _("Validate")
        return {
            "url": reverse("validate") + "?file_id=" + str(obj.id),  # decide where the button links to
            "label": text,
            "classname": self.finalise_classname(self.validate_button_classnames),
            "title": text,
        }

    def import_button(self, obj):
        # Define a label for our button
        text = _("Import")
        return {
            "url": reverse("import_file"),  # decide where the button links to
            "label": text,
            "classname": self.finalise_classname(self.import_button_classnames),
            "title": text,
        }

    def get_buttons_for_obj(
        self, obj, exclude=None, classnames_add=None, classnames_exclude=None
    ):
        """
        This function is used to gather all available buttons.
        We append our custom button to the btns list.
        """
        btns = super().get_buttons_for_obj(
            obj, exclude, classnames_add, classnames_exclude
        )
        if "validate" not in (exclude or []):
            btns.append(self.validate_button(obj))
        if "import" not in (exclude or []):
            btns.append(self.import_button(obj))
        return btns

Access http://localhost:8000/admin/source_directory/sourcedirectoryfile/ and see this interface: