From 13ff98917de1216525b7fe51b90b6cbb0343eed2 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 27 Sep 2018 12:14:04 +0200 Subject: Admin: import town from CSV --- ishtar_common/admin.py | 237 +++++++++++++++++++++++++------------------------ 1 file changed, 122 insertions(+), 115 deletions(-) (limited to 'ishtar_common/admin.py') diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 6ae455e53..dfe2becb3 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -221,52 +221,6 @@ class PersonAdmin(HistorizedObjectAdmin): admin_site.register(models.Person, PersonAdmin) -class AdminRelatedTownForm(forms.ModelForm): - class Meta: - model = models.Town.children.through - exclude = [] - from_town = AutoCompleteSelectField( - 'town', required=True, label=_(u"Parent")) - - -class AdminTownForm(forms.ModelForm): - class Meta: - model = models.Town - exclude = ['imports'] - center = PointField(label=_(u"Center"), required=False, - widget=OSMWidget) - limit = MultiPolygonField(label=_(u"Limit"), required=False, - widget=OSMWidget) - children = AutoCompleteSelectMultipleField('town', required=False, - label=_(u"Town children")) - - -class TownParentInline(admin.TabularInline): - model = models.Town.children.through - fk_name = 'to_town' - form = AdminRelatedTownForm - verbose_name = _(u"Parent") - verbose_name_plural = _(u"Parents") - extra = 1 - - -class TownAdmin(admin.ModelAdmin): - model = models.Town - list_display = ['name', 'year'] - search_fields = ['name'] - readonly_fields = ['cached_label'] - if settings.COUNTRY == 'fr': - list_display += ['numero_insee'] - search_fields += ['numero_insee', 'departement__label', ] - list_filter = ("departement",) - form = AdminTownForm - inlines = [TownParentInline] - actions = [export_as_csv_action(exclude=['center', 'limit'])] - - -admin_site.register(models.Town, TownAdmin) - - class AuthorAdmin(admin.ModelAdmin): list_display = ['person', 'author_type'] list_filter = ("author_type",) @@ -306,77 +260,17 @@ class ChangeListForChangeView(ChangeList): return filtered_params -class GeneralTypeAdmin(admin.ModelAdmin): - list_display = ['label', 'txt_idx', 'available', 'comment'] - search_fields = ('label', 'txt_idx', 'comment',) - list_filter = ('available',) - save_on_top = True - actions = [export_as_csv_action()] - prepopulated_fields = {"txt_idx": ("label",)} +class ImportActionAdmin(admin.ModelAdmin): change_list_template = "admin/gen_change_list.html" + import_keys = ['slug', 'txt_idx'] def get_urls(self): - urls = super(GeneralTypeAdmin, self).get_urls() + urls = super(ImportActionAdmin, self).get_urls() my_urls = [ url(r'^import-from-csv/$', self.import_generic), ] return my_urls + urls - @csrf_protect_m - def get_changelist_queryset(self, request): - """ - Get the changelist queryset to be used in the change view. - Used by previous and next button. - Mainly a copy from: - django/contrib/admin/options.py ModelAdmin->changelist_view - """ - list_display = self.get_list_display(request) - list_display_links = self.get_list_display_links(request, list_display) - list_filter = self.get_list_filter(request) - search_fields = self.get_search_fields(request) - list_select_related = self.get_list_select_related(request) - - cl = ChangeListForChangeView( - request, self.model, list_display, - list_display_links, list_filter, self.date_hierarchy, - search_fields, list_select_related, self.list_per_page, - self.list_max_show_all, self.list_editable, self, - ) - return cl.get_queryset(request) - - def change_view(self, request, object_id, form_url='', extra_context=None): - """ - Next and previous button on the change view - """ - if not extra_context: - extra_context = {} - ids = list(self.get_changelist_queryset(request).values('pk')) - previous, current_is_reached, first = None, False, None - extra_context['get_attr'] = "" - if request.GET: - extra_context['get_attr'] = "?" + request.GET.urlencode() - for v in ids: - pk = str(v['pk']) - if pk == object_id: - current_is_reached = True - if previous: - extra_context['previous_item'] = previous - elif current_is_reached: - extra_context['next_item'] = pk - break - else: - if not first: - first = pk - previous = pk - if 'previous_item' not in extra_context and \ - 'next_item' not in extra_context and first: - # on modify current object do not match current criteria - # next is the first item - extra_context['next_item'] = first - - return super(GeneralTypeAdmin, self).change_view( - request, object_id, form_url, extra_context) - def import_generic(self, request): form = None @@ -387,15 +281,17 @@ class GeneralTypeAdmin(admin.ModelAdmin): reader = csv.DictReader(csv_file) created, updated, missing_parent = 0, 0, [] for row in reader: - if 'slug' in row: - slug_col = 'slug' - elif 'txt_idx' in row: - slug_col = 'txt_idx' - else: + slug_col = None + for key in self.import_keys: + if key in row: + slug_col = key + break + if not slug_col: self.message_user( request, unicode(_(u"The CSV file should at least have a " - u"slug/txt_idx column"))) + u"{} column")).format( + u"/".join(self.import_keys))) return slug = row.pop(slug_col) if 'id' in row: @@ -472,6 +368,117 @@ class GeneralTypeAdmin(admin.ModelAdmin): return render(request, 'admin/import_from_csv.html', {'csv_form': form}) +class AdminRelatedTownForm(forms.ModelForm): + class Meta: + model = models.Town.children.through + exclude = [] + from_town = AutoCompleteSelectField( + 'town', required=True, label=_(u"Parent")) + + +class AdminTownForm(forms.ModelForm): + class Meta: + model = models.Town + exclude = ['imports'] + center = PointField(label=_(u"Center"), required=False, + widget=OSMWidget) + limit = MultiPolygonField(label=_(u"Limit"), required=False, + widget=OSMWidget) + children = AutoCompleteSelectMultipleField('town', required=False, + label=_(u"Town children")) + + +class TownParentInline(admin.TabularInline): + model = models.Town.children.through + fk_name = 'to_town' + form = AdminRelatedTownForm + verbose_name = _(u"Parent") + verbose_name_plural = _(u"Parents") + extra = 1 + + +class TownAdmin(ImportActionAdmin): + model = models.Town + list_display = ['name', 'year'] + search_fields = ['name'] + readonly_fields = ['cached_label'] + if settings.COUNTRY == 'fr': + list_display += ['numero_insee'] + search_fields += ['numero_insee', 'departement__label', ] + list_filter = ("departement",) + form = AdminTownForm + inlines = [TownParentInline] + actions = [export_as_csv_action(exclude=['center', 'limit'])] + import_keys = ['slug', 'txt_idx', 'numero_insee'] + + +admin_site.register(models.Town, TownAdmin) + + +class GeneralTypeAdmin(ImportActionAdmin): + list_display = ['label', 'txt_idx', 'available', 'comment'] + search_fields = ('label', 'txt_idx', 'comment',) + list_filter = ('available',) + save_on_top = True + actions = [export_as_csv_action()] + prepopulated_fields = {"txt_idx": ("label",)} + + @csrf_protect_m + def get_changelist_queryset(self, request): + """ + Get the changelist queryset to be used in the change view. + Used by previous and next button. + Mainly a copy from: + django/contrib/admin/options.py ModelAdmin->changelist_view + """ + list_display = self.get_list_display(request) + list_display_links = self.get_list_display_links(request, list_display) + list_filter = self.get_list_filter(request) + search_fields = self.get_search_fields(request) + list_select_related = self.get_list_select_related(request) + + cl = ChangeListForChangeView( + request, self.model, list_display, + list_display_links, list_filter, self.date_hierarchy, + search_fields, list_select_related, self.list_per_page, + self.list_max_show_all, self.list_editable, self, + ) + return cl.get_queryset(request) + + def change_view(self, request, object_id, form_url='', extra_context=None): + """ + Next and previous button on the change view + """ + if not extra_context: + extra_context = {} + ids = list(self.get_changelist_queryset(request).values('pk')) + previous, current_is_reached, first = None, False, None + extra_context['get_attr'] = "" + if request.GET: + extra_context['get_attr'] = "?" + request.GET.urlencode() + for v in ids: + pk = str(v['pk']) + if pk == object_id: + current_is_reached = True + if previous: + extra_context['previous_item'] = previous + elif current_is_reached: + extra_context['next_item'] = pk + break + else: + if not first: + first = pk + previous = pk + if 'previous_item' not in extra_context and \ + 'next_item' not in extra_context and first: + # on modify current object do not match current criteria + # next is the first item + extra_context['next_item'] = first + + return super(GeneralTypeAdmin, self).change_view( + request, object_id, form_url, extra_context) + + general_models = [models.OrganizationType, models.SourceType, models.AuthorType, models.TitleType, models.Format, models.SupportType, models.PersonType, models.LicenseType] -- cgit v1.2.3