Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement import export library #3381

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 152 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ qrcode = {version = "^7.4.2", extras = ["pil"]}
freezegun = "1.2.2"
PyYAML = "6.0.1"
celery = {version = "^5.3.1", extras = ["redis"]}
django-import-export = "3.3.1"

[tool.poetry.group.scss.dependencies]
# These dependencies are only needed to compile SASS, which can be done
Expand Down
57 changes: 9 additions & 48 deletions website/activemembers/admin.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
"""Registers admin interfaces for the activemembers module."""
import csv
import datetime

from django import forms
from django.contrib import admin, messages
from django.db.models import Q
from django.http import HttpResponse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from import_export.admin import ExportActionMixin

from activemembers import models
from activemembers.forms import MemberGroupForm, MemberGroupMembershipForm
from activemembers.resources import MemberGroupMembershipResource
from utils.snippets import datetime_to_lectureyear


class MemberGroupMembershipInlineFormSet(forms.BaseInlineFormSet):
"""Here for performance reasons, and to filter out old memberships.
"""Solely here for performance reasons.

Needed because the `__str__()` of `MemberGroupMembership` (which is
displayed above each inline form) uses the username, name of the member
Expand All @@ -25,14 +26,9 @@ class MemberGroupMembershipInlineFormSet(forms.BaseInlineFormSet):
def __init__(self, *args, **kwargs):
"""Initialize and set queryset."""
super().__init__(*args, **kwargs)
now = timezone.now()
self.queryset = self.queryset.select_related("member", "group")

# Show only memberships that are active now.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you delete this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I think what happened is that when I copied the code from the older branch (which was a mess), I accidentally copied the old implementation for this class as well. I've fixed it now locally.

Unfortunately, I've also found another issue, because it seems like it's not possible to export only selected users from the separate Member export page. You can only export every member. I'll see if I can find a solution before pushing.

if not isinstance(self.instance, models.Board):
self.queryset = self.queryset.filter(
Q(until=None) | (Q(since__lte=now, until__gte=now))
)
self.queryset = self.queryset.select_related("member", "group").filter(
until=None
)


class MemberGroupMembershipInline(admin.StackedInline):
Expand Down Expand Up @@ -177,9 +173,10 @@ def queryset(self, request, queryset):


@admin.register(models.MemberGroupMembership)
class MemberGroupMembershipAdmin(admin.ModelAdmin):
class MemberGroupMembershipAdmin(ExportActionMixin, admin.ModelAdmin):
"""Manage the group memberships."""

resource_classes = (MemberGroupMembershipResource,)
form = MemberGroupMembershipForm
list_display = ("member", "group", "since", "until", "chair", "role")
list_filter = ("group", TypeFilter, LectureYearFilter, ActiveMembershipsFilter)
Expand All @@ -189,7 +186,6 @@ class MemberGroupMembershipAdmin(admin.ModelAdmin):
)
search_fields = ("member__first_name", "member__last_name", "member__email")
date_hierarchy = "since"
actions = ("export",)

def changelist_view(self, request, extra_context=None):
self.message_user(
Expand All @@ -203,41 +199,6 @@ def changelist_view(self, request, extra_context=None):
)
return super().changelist_view(request, extra_context)

def export(self, request, queryset):
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="group_memberships.csv"'
writer = csv.writer(response)
writer.writerow(
[
_("First name"),
_("Last name"),
_("Email"),
_("Group"),
_("Member since"),
_("Member until"),
_("Chair of the group"),
_("Role"),
]
)

for membership in queryset:
writer.writerow(
[
membership.member.first_name,
membership.member.last_name,
membership.member.email,
membership.group,
membership.since,
membership.until,
membership.chair,
membership.role,
]
)

return response

export.short_description = _("Export selected memberships")


@admin.register(models.Mentorship)
class MentorshipAdmin(admin.ModelAdmin):
Expand Down
38 changes: 38 additions & 0 deletions website/activemembers/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from import_export import resources
from import_export.fields import Field

from activemembers.models import MemberGroupMembership


class MemberGroupMembershipResource(resources.ModelResource):
first_name = Field(column_name="First name")
last_name = Field(column_name="Last name")
email = Field(column_name="Email")
group = Field(attribute="group", column_name="Group")
since = Field(attribute="since", column_name="Member since")
until = Field(attribute="until", column_name="Member until")
chair = Field(attribute="chair", column_name="Chair of the group")
role = Field(attribute="role", column_name="Role")

class Meta:
model = MemberGroupMembership
fields = (
"first_name",
"last_name",
"email",
"group",
"since",
"until",
"chair",
"role",
)
export_order = fields

def dehydrate_first_name(self, membership):
return membership.member.first_name

def dehydrate_last_name(self, membership):
return membership.member.last_name

def dehydrate_email(self, membership):
return membership.member.email
Loading