diff --git a/account/admin.py b/account/admin.py index 9ef3a32..fe85096 100644 --- a/account/admin.py +++ b/account/admin.py @@ -1,6 +1,8 @@ from django import forms from django.contrib import admin +from profiles.admin import DisableAddAdminMixin, DisableDeleteAdminMixin + from .models import MailingList, Profile, User admin.site.register(User) @@ -24,7 +26,7 @@ class Meta: fields = ["result"] -class MailingListAdmin(admin.ModelAdmin): +class MailingListAdmin(DisableDeleteAdminMixin, DisableAddAdminMixin, admin.ModelAdmin): list_display = ("result", "csv_emails") readonly_fields = ("result",) diff --git a/profiles/admin.py b/profiles/admin.py index 80226ba..6860b02 100644 --- a/profiles/admin.py +++ b/profiles/admin.py @@ -1,4 +1,7 @@ +import csv + from django.contrib import admin +from django.http import HttpResponse from profiles.models import ( Answer, @@ -15,7 +18,12 @@ ) -class ReadOnlyFieldsAdminMixin: +class DisableAddAdminMixin: + def has_add_permission(self, request, obj=None): + return False + + +class DisableChangeAdminMixin: def has_change_permission(self, request, obj=None): return False @@ -25,42 +33,63 @@ def has_delete_permission(self, request, obj=None): return False -class QuestionAdmin(DisableDeleteAdminMixin, admin.ModelAdmin): +class QuestionAdmin(DisableDeleteAdminMixin, DisableAddAdminMixin, admin.ModelAdmin): class Meta: model = Question class QuestionConditionAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): class Meta: model = QuestionCondition -class SubQuestionAdmin(DisableDeleteAdminMixin, admin.ModelAdmin): +class SubQuestionAdmin(DisableDeleteAdminMixin, DisableAddAdminMixin, admin.ModelAdmin): class Meta: model = Question -class ResultAdmin(DisableDeleteAdminMixin, admin.ModelAdmin): +class ResultAdmin( + DisableDeleteAdminMixin, + DisableAddAdminMixin, + DisableChangeAdminMixin, + admin.ModelAdmin, +): class Meta: model = Result class SubQuestionConditionAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): class Meta: model = SubQuestionCondition -class OptionAdmin(DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin): +class OptionAdmin( + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, +): class Meta: model = Option @admin.register(Answer) -class AnswerAdmin(DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin): +class AnswerAdmin( + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, +): def get_queryset(self, request): qs = super().get_queryset(request) qs = qs.filter(option__is_other=False) @@ -72,14 +101,46 @@ class Meta: @admin.register(AnswerOther) class AnswerOtherAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): + queryset = Answer.objects.filter(other__isnull=False) + actions = ["export_as_csv"] + list_per_page = 10000 list_display = ( "question_description", "sub_question_description", "other", ) + def export_as_csv(self, request, queryset): + meta = self.model._meta + queryset = queryset.order_by("question", "sub_question") + field_names = ["id", "created", "question", "sub_question", "option", "other"] + str_fields = ["question", "sub_question", "other"] + response = HttpResponse(content_type="text/csv") + response["Content-Disposition"] = "attachment; filename={}.csv".format(meta) + writer = csv.writer(response) + writer.writerow(field_names) + for obj in queryset: + row = [] + for field in field_names: + attr = getattr(obj, field) + if field == "question" and attr is None: + attr = obj.sub_question.question + if field in str_fields: + attr = ( + str(attr).replace('"', "'").replace("\n", " ").replace("\r", "") + ) + row.append(attr) + writer.writerow(row) + + return response + + export_as_csv.short_description = "Export selected as CSV" + def get_queryset(self, request): qs = super().get_queryset(request) qs = qs.filter(option__is_other=True) @@ -104,21 +165,30 @@ class Meta: class PostalCodeAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): class Meta: model = PostalCode class PostalCodeTypeAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): class Meta: model = PostalCodeType class PostalCodeResultAdmin( - DisableDeleteAdminMixin, ReadOnlyFieldsAdminMixin, admin.ModelAdmin + DisableDeleteAdminMixin, + DisableChangeAdminMixin, + DisableAddAdminMixin, + admin.ModelAdmin, ): list_display = ("postal_code", "postal_code_type", "result", "count") diff --git a/profiles/models.py b/profiles/models.py index 8c26a0d..2bb56c8 100644 --- a/profiles/models.py +++ b/profiles/models.py @@ -14,7 +14,7 @@ class Meta: ordering = ["id"] def __str__(self): - return f"question number:{self.number}, question: {self.question}" + return f"{self.number}: {self.question}" @property def num_sub_questions(self): @@ -53,7 +53,7 @@ class Meta: ordering = ["order_number"] def __str__(self): - return f"Value: {self.value}" + return f"{self.value}" class Result(models.Model):