diff --git a/basedosdados_api/api/v1/admin.py b/basedosdados_api/api/v1/admin.py index 165dbc8b..61f84850 100644 --- a/basedosdados_api/api/v1/admin.py +++ b/basedosdados_api/api/v1/admin.py @@ -8,6 +8,7 @@ from django.contrib import admin, messages from django.core.management import call_command from django.db.models.query import QuerySet +from django.forms.models import BaseInlineFormSet from django.shortcuts import get_object_or_404, render from django.utils.html import format_html from google.api_core.exceptions import BadRequest, NotFound @@ -21,10 +22,12 @@ TableCoverageFilter, TableObservationFilter, ) -from basedosdados_api.api.v1.forms import ReorderColumnsForm, ReorderTablesForm -from basedosdados_api.api.v1.forms.admin_forms import ( +from basedosdados_api.api.v1.forms import ( ColumnInlineForm, CoverageInlineForm, + ObservationLevelForm, + ReorderColumnsForm, + ReorderTablesForm, TableInlineForm, ) from basedosdados_api.api.v1.models import ( @@ -60,6 +63,162 @@ logger = getLogger("django") +################################################################################ +# Model Admins Inlines +################################################################################ + + +class TranslateOrderedInline(OrderedStackedInline, TranslationStackedInline): + pass + + +class CustomObservationLevelInlineFormset(BaseInlineFormSet): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + columns_queryset = self.instance.columns.all() + + for form in self.forms: + form.fields["column_choice"].queryset = columns_queryset + + +class ObservationLevelInline(admin.StackedInline): + model = ObservationLevel + form = ObservationLevelForm + formset = CustomObservationLevelInlineFormset + template = "admin/edit_inline/stacked_table_observation_level.html" + extra = 0 + + fields = [ + "id", + "entity", + "column_choice", + ] + autocomplete_fields = [ + "entity", + ] + + +class ColumnInline(TranslateOrderedInline): + model = Column + form = ColumnInlineForm + extra = 0 + show_change_link = True + show_full_result_count = True + autocomplete_fields = [ + "directory_primary_key", + "observation_level", + ] + fields = [ + "order", + "move_up_down_links", + ] + ColumnInlineForm.Meta.fields + readonly_fields = [ + "order", + "move_up_down_links", + ] + ordering = [ + "order", + ] + + +class TableInline(TranslateOrderedInline): + model = Table + form = TableInlineForm + extra = 0 + show_change_link = True + fields = [ + "order", + "move_up_down_links", + ] + TableInlineForm.Meta.fields + readonly_fields = [ + "order", + "move_up_down_links", + ] + ordering = [ + "order", + ] + + +class RawDataSourceInline(TranslateOrderedInline): + model = RawDataSource + extra = 0 + show_change_link = True + fields = [ + "order", + "move_up_down_links", + "id", + "name", + "description", + "url", + ] + readonly_fields = [ + "order", + "move_up_down_links", + ] + ordering = [ + "order", + ] + + +class InformationRequestInline(TranslateOrderedInline): + model = InformationRequest + extra = 0 + show_change_link = True + fields = [ + "order", + "move_up_down_links", + "id", + "origin", + "number", + "url", + ] + readonly_fields = [ + "order", + "move_up_down_links", + ] + ordering = [ + "order", + ] + + +class DateTimeRangeInline(admin.StackedInline): + model = DateTimeRange + extra = 0 + show_change_link = True + + +class CoverageTableInline(admin.StackedInline): + model = Coverage + form = CoverageInlineForm + extra = 0 + show_change_link = True + exclude = [ + "raw_data_source", + "information_request", + "column", + "key", + "analysis", + ] + readonly_fields = [ + "id", + "area", + # "table", + ] + inlines = [ + DateTimeRangeInline, + ] + # template = "admin/edit_inline/custom_coverage_model_inline.html" + # inlines = [ + # TableCoverageFilter, + # ] + # formfield_overrides = {models.TextField: {"widget": AdminMartorWidget}} + + +################################################################################ +# Model Admins Actions +################################################################################ + + def get_credentials(): """Get google cloud credentials""" credentials_dict = json.loads(settings.GOOGLE_APPLICATION_CREDENTIALS) @@ -200,130 +359,11 @@ def rebuild_search_index(modeladmin, request, queryset): rebuild_search_index.short_description = "Rebuild search index" -class TranslateOrderedInline(OrderedStackedInline, TranslationStackedInline): - pass - - -# Inlines - - -class ColumnInline(TranslateOrderedInline): - model = Column - form = ColumnInlineForm - extra = 0 - show_change_link = True - show_full_result_count = True - autocomplete_fields = [ - "directory_primary_key", - "observation_level", - ] - fields = [ - "order", - "move_up_down_links", - ] + ColumnInlineForm.Meta.fields - readonly_fields = [ - "order", - "move_up_down_links", - ] - ordering = [ - "order", - ] - - -class TableInline(TranslateOrderedInline): - model = Table - form = TableInlineForm - extra = 0 - show_change_link = True - fields = [ - "order", - "move_up_down_links", - ] + TableInlineForm.Meta.fields - readonly_fields = [ - "order", - "move_up_down_links", - ] - ordering = [ - "order", - ] - - -class RawDataSourceInline(TranslateOrderedInline): - model = RawDataSource - extra = 0 - show_change_link = True - fields = [ - "order", - "move_up_down_links", - "id", - "name", - "description", - "url", - ] - readonly_fields = [ - "order", - "move_up_down_links", - ] - ordering = [ - "order", - ] - - -class InformationRequestInline(TranslateOrderedInline): - model = InformationRequest - extra = 0 - show_change_link = True - fields = [ - "order", - "move_up_down_links", - "id", - "origin", - "number", - "url", - ] - readonly_fields = [ - "order", - "move_up_down_links", - ] - ordering = [ - "order", - ] - - -class DateTimeRangeInline(admin.StackedInline): - model = DateTimeRange - extra = 0 - show_change_link = True - - -class CoverageTableInline(admin.StackedInline): - model = Coverage - form = CoverageInlineForm - extra = 0 - show_change_link = True - exclude = [ - "raw_data_source", - "information_request", - "column", - "key", - "analysis", - ] - readonly_fields = [ - "id", - "area", - # "table", - ] - inlines = [ - DateTimeRangeInline, - ] - # template = "admin/edit_inline/custom_coverage_model_inline.html" - # inlines = [ - # TableCoverageFilter, - # ] - # formfield_overrides = {models.TextField: {"widget": AdminMartorWidget}} +################################################################################ +# Model Admins +################################################################################ -# Model Admins class AreaAdmin(TabbedTranslationAdmin): readonly_fields = [ "id", @@ -529,6 +569,7 @@ def add_view(self, request, *args, **kwargs): search_fields = ["name", "dataset__name"] inlines = [ ColumnInline, + ObservationLevelInline, ] autocomplete_fields = [ "dataset", @@ -542,6 +583,25 @@ def add_view(self, request, *args, **kwargs): TableObservationFilter, ] + def save_formset(self, request, form, formset, change): + """Saves the formset, adding the table to the dataset""" + if formset.model == ObservationLevel: + instances = formset.save(commit=False) # noqa + for form in formset.forms: + if form.instance.pk: + Column.objects.filter(observation_level=form.instance).update( + observation_level=None + ) + form_instance = form.save(commit=False) + column_instance = form.cleaned_data.get("column_choice") + if column_instance: + column_instance.observation_level = form_instance + column_instance.save() + form_instance.save() + formset.save_m2m() + else: + formset.save() + class ColumnForm(forms.ModelForm): class Meta: @@ -596,9 +656,6 @@ class ObservationLevelAdmin(admin.ModelAdmin): "raw_data_source", "information_request", ] - # inlines = [ - # ColumnInline, - # ] class RawDataSourceAdmin(TabbedTranslationAdmin): diff --git a/basedosdados_api/api/v1/forms/__init__.py b/basedosdados_api/api/v1/forms/__init__.py index 2b06fe30..49a742b6 100644 --- a/basedosdados_api/api/v1/forms/__init__.py +++ b/basedosdados_api/api/v1/forms/__init__.py @@ -1,3 +1,9 @@ # -*- coding: utf-8 -*- -from .reorder_columns_form import ReorderColumnsForm # noqa: F401 -from .reorder_tables_form import ReorderTablesForm # noqa: F401 +from basedosdados_api.api.v1.forms.admin_form import ( # noqa: F401 + ColumnInlineForm, + CoverageInlineForm, + ObservationLevelForm, + TableInlineForm, +) +from basedosdados_api.api.v1.forms.reorder_columns_form import ReorderColumnsForm # noqa: F401 +from basedosdados_api.api.v1.forms.reorder_tables_form import ReorderTablesForm # noqa: F401 diff --git a/basedosdados_api/api/v1/forms/admin_forms.py b/basedosdados_api/api/v1/forms/admin_form.py similarity index 72% rename from basedosdados_api/api/v1/forms/admin_forms.py rename to basedosdados_api/api/v1/forms/admin_form.py index d6aaf4de..405f0074 100644 --- a/basedosdados_api/api/v1/forms/admin_forms.py +++ b/basedosdados_api/api/v1/forms/admin_form.py @@ -1,5 +1,13 @@ # -*- coding: utf-8 -*- -from basedosdados_api.api.v1.models import Column, Coverage, Table, UUIDHIddenIdForm +from django import forms + +from basedosdados_api.api.v1.models import ( + Column, + Coverage, + ObservationLevel, + Table, + UUIDHIddenIdForm, +) class TableInlineForm(UUIDHIddenIdForm): @@ -55,6 +63,19 @@ class Meta(UUIDHIddenIdForm.Meta): ] +class ObservationLevelForm(UUIDHIddenIdForm): + column_choice = forms.ModelChoiceField(label="Column", queryset=Column.objects.all()) + + class Meta(UUIDHIddenIdForm.Meta): + model = ObservationLevel + fields = "__all__" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.instance.pk: + self.initial["column_choice"] = self.instance.columns.first() + + class CoverageInlineForm(UUIDHIddenIdForm): class Meta(UUIDHIddenIdForm.Meta): model = Coverage diff --git a/basedosdados_api/api/v1/templates/admin/edit_inline/stacked_table_observation_level.html b/basedosdados_api/api/v1/templates/admin/edit_inline/stacked_table_observation_level.html new file mode 100644 index 00000000..74a6175a --- /dev/null +++ b/basedosdados_api/api/v1/templates/admin/edit_inline/stacked_table_observation_level.html @@ -0,0 +1,16 @@ +{% load i18n admin_urls static %} +
+
+
+ {{ inline_admin_formset.formset.management_form }} + {{ inline_admin_formset.formset.non_form_errors }} + {% for field in inline_admin_formset.formset %} + {{ field.id}}
+ {{ field.entity.label_tag }} {{field.entity}}
+ {{ field.column_choice.label_tag }}
{{ field.column_choice }} +
+ {% endfor %} + +
+
+