Aller au contenu

Views

ClubAdminEditForm

Bases: ClubEditForm

ClubEditForm

Bases: ModelForm

ClubMemberForm(*args, **kwargs)

Bases: Form

Form handling the members of a club.

Source code in club/forms.py
def __init__(self, *args, **kwargs):
    self.club = kwargs.pop("club")
    self.request_user = kwargs.pop("request_user")
    self.club_members = kwargs.pop("club_members", None)
    if not self.club_members:
        self.club_members = self.club.members.ongoing().order_by("-role").all()
    self.request_user_membership = self.club.get_membership_for(self.request_user)
    super().__init__(*args, **kwargs)

    # Using a ModelForm binds too much the form with the model and we don't want that
    # We want the view to process the model creation since they are multiple users
    # We also want the form to handle bulk deletion
    self.fields.update(
        forms.fields_for_model(
            Membership,
            fields=("role", "start_date", "description"),
            widgets={"start_date": SelectDate},
        )
    )

    # Role is required only if users is specified
    self.fields["role"].required = False

    # Start date and description are never really required
    self.fields["start_date"].required = False
    self.fields["description"].required = False

    self.fields["users_old"] = forms.ModelMultipleChoiceField(
        User.objects.filter(
            id__in=[
                ms.user.id
                for ms in self.club_members
                if ms.can_be_edited_by(self.request_user)
            ]
        ).all(),
        label=_("Mark as old"),
        required=False,
        widget=forms.CheckboxSelectMultiple,
    )
    if not self.request_user.is_root:
        self.fields.pop("start_date")

clean_users()

Check that the user is not trying to add an user already in the club.

Also check that the user is valid and has a valid subscription.

Source code in club/forms.py
def clean_users(self):
    """Check that the user is not trying to add an user already in the club.

    Also check that the user is valid and has a valid subscription.
    """
    cleaned_data = super().clean()
    users = []
    for user in cleaned_data["users"]:
        if not user.is_subscribed:
            raise forms.ValidationError(
                _("User must be subscriber to take part to a club"), code="invalid"
            )
        if self.club.get_membership_for(user):
            raise forms.ValidationError(
                _("You can not add the same user twice"), code="invalid"
            )
        users.append(user)
    return users

clean()

Check user rights for adding an user.

Source code in club/forms.py
def clean(self):
    """Check user rights for adding an user."""
    cleaned_data = super().clean()

    if "start_date" in cleaned_data and not cleaned_data["start_date"]:
        # Drop start_date if allowed to edition but not specified
        cleaned_data.pop("start_date")

    if not cleaned_data.get("users"):
        # No user to add equals no check needed
        return cleaned_data

    if cleaned_data.get("role", "") == "":
        # Role is required if users exists
        self.add_error("role", _("You should specify a role"))
        return cleaned_data

    request_user = self.request_user
    membership = self.request_user_membership
    if not (
        cleaned_data["role"] <= settings.SITH_MAXIMUM_FREE_ROLE
        or (membership is not None and membership.role >= cleaned_data["role"])
        or request_user.is_board_member
        or request_user.is_root
    ):
        raise forms.ValidationError(_("You do not have the permission to do that"))
    return cleaned_data

MailingForm(club_id, user_id, mailings, *args, **kwargs)

Bases: Form

Form handling mailing lists right.

Source code in club/forms.py
def __init__(self, club_id, user_id, mailings, *args, **kwargs):
    super().__init__(*args, **kwargs)

    self.fields["action"] = forms.TypedChoiceField(
        choices=(
            (self.ACTION_NEW_MAILING, _("New Mailing")),
            (self.ACTION_NEW_SUBSCRIPTION, _("Subscribe")),
            (self.ACTION_REMOVE_SUBSCRIPTION, _("Remove")),
        ),
        coerce=int,
        label=_("Action"),
        initial=1,
        required=True,
        widget=forms.HiddenInput(),
    )

    # Generate bulk removal forms, they are never required
    for mailing in mailings:
        self.fields["removal_" + str(mailing.id)] = forms.ModelMultipleChoiceField(
            mailing.subscriptions.all(),
            label=_("Remove"),
            required=False,
            widget=forms.CheckboxSelectMultiple,
        )

    # Include fields for handling mailing creation
    mailing_fields = ("email",)
    self.fields.update(forms.fields_for_model(Mailing, fields=mailing_fields))
    for field in mailing_fields:
        self.fields["mailing_" + field] = self.fields.pop(field)
        self.fields["mailing_" + field].required = False

    # Include fields for handling subscription creation
    subscription_fields = ("mailing", "email")
    self.fields.update(
        forms.fields_for_model(MailingSubscription, fields=subscription_fields)
    )
    for field in subscription_fields:
        self.fields["subscription_" + field] = self.fields.pop(field)
        self.fields["subscription_" + field].required = False

    self.fields["subscription_mailing"].queryset = Mailing.objects.filter(
        club__id=club_id, is_moderated=True
    )

check_required(cleaned_data, field)

If the given field doesn't exist or has no value, add a required error on it.

Source code in club/forms.py
def check_required(self, cleaned_data, field):
    """If the given field doesn't exist or has no value, add a required error on it."""
    if not cleaned_data.get(field, None):
        self.add_error(field, _("This field is required"))

clean_subscription_users()

Convert given users into real users and check their validity.

Source code in club/forms.py
def clean_subscription_users(self):
    """Convert given users into real users and check their validity."""
    cleaned_data = super().clean()
    users = []
    for user in cleaned_data["subscription_users"]:
        if not user.email:
            raise forms.ValidationError(
                _("One of the selected users doesn't have an email address"),
                code="invalid",
            )
        users.append(user)
    return users

SellingsForm(club, *args, **kwargs)

Bases: Form

Source code in club/forms.py
def __init__(self, club, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields["products"] = forms.ModelMultipleChoiceField(
        club.products.order_by("name").filter(archived=False).all(),
        label=_("Products"),
        required=False,
    )
    self.fields["archived_products"] = forms.ModelMultipleChoiceField(
        club.products.order_by("name").filter(archived=True).all(),
        label=_("Archived products"),
        required=False,
    )

Club

Bases: Model

The Club class, made as a tree to allow nice tidy organization.

president()

Fetch the membership of the current president of this club.

Source code in club/models.py
@cached_property
def president(self) -> Membership | None:
    """Fetch the membership of the current president of this club."""
    return self.members.filter(
        role=settings.SITH_CLUB_ROLES_ID["President"], end_date=None
    ).first()

check_loop()

Raise a validation error when a loop is found within the parent list.

Source code in club/models.py
def check_loop(self):
    """Raise a validation error when a loop is found within the parent list."""
    objs = []
    cur = self
    while cur.parent is not None:
        if cur in objs:
            raise ValidationError(_("You can not make loops in clubs"))
        objs.append(cur)
        cur = cur.parent

is_owned_by(user)

Method to see if that object can be super edited by the given user.

Source code in club/models.py
def is_owned_by(self, user: User) -> bool:
    """Method to see if that object can be super edited by the given user."""
    if user.is_anonymous:
        return False
    return user.is_root or user.is_board_member

can_be_edited_by(user)

Method to see if that object can be edited by the given user.

Source code in club/models.py
def can_be_edited_by(self, user: User) -> bool:
    """Method to see if that object can be edited by the given user."""
    return self.has_rights_in_club(user)

can_be_viewed_by(user)

Method to see if that object can be seen by the given user.

Source code in club/models.py
def can_be_viewed_by(self, user: User) -> bool:
    """Method to see if that object can be seen by the given user."""
    return user.was_subscribed

get_membership_for(user)

Return the current membership the given user.

Note

The result is cached.

Source code in club/models.py
def get_membership_for(self, user: User) -> Membership | None:
    """Return the current membership the given user.

    Note:
        The result is cached.
    """
    if user.is_anonymous:
        return None
    membership = cache.get(f"membership_{self.id}_{user.id}")
    if membership == "not_member":
        return None
    if membership is None:
        membership = self.members.filter(user=user, end_date=None).first()
        if membership is None:
            cache.set(f"membership_{self.id}_{user.id}", "not_member")
        else:
            cache.set(f"membership_{self.id}_{user.id}", membership)
    return membership

Mailing

Bases: Model

A Mailing list for a club.

Warning

Remember that mailing lists should be validated by UTBM.

MailingSubscription

Bases: Model

Link between user and mailing list.

Membership

Bases: Model

The Membership class makes the connection between User and Clubs.

Both Users and Clubs can have many Membership objects
  • a user can be a member of many clubs at a time
  • a club can have many members at a time too

A User is currently member of all the Clubs where its Membership has an end_date set to null/None. Otherwise, it's a past membership kept because it can be very useful to see who was in which Club in the past.

is_owned_by(user)

Method to see if that object can be super edited by the given user.

Source code in club/models.py
def is_owned_by(self, user: User) -> bool:
    """Method to see if that object can be super edited by the given user."""
    if user.is_anonymous:
        return False
    return user.is_root or user.is_board_member

can_be_edited_by(user)

Check if that object can be edited by the given user.

Source code in club/models.py
def can_be_edited_by(self, user: User) -> bool:
    """Check if that object can be edited by the given user."""
    if user.is_root or user.is_board_member:
        return True
    membership = self.club.get_membership_for(user)
    return membership is not None and membership.role >= self.role

ClubTabsMixin

ClubListView

Bases: ListView

List the Clubs.

ClubView

Bases: ClubTabsMixin, DetailView

Front page of a Club.

ClubRevView

Bases: ClubView

Display a specific page revision.

ClubPageEditView

ClubPageHistView

Bases: ClubTabsMixin, CanViewMixin, DetailView

Modification hostory of the page.

ClubToolsView

Bases: ClubTabsMixin, CanEditMixin, DetailView

Tools page of a Club.

ClubMembersView

Bases: ClubTabsMixin, CanViewMixin, DetailFormView

View of a club's members.

form_valid(form)

Check user rights.

Source code in club/views.py
def form_valid(self, form):
    """Check user rights."""
    resp = super().form_valid(form)

    data = form.clean()
    users = data.pop("users", [])
    users_old = data.pop("users_old", [])
    for user in users:
        Membership(club=self.object, user=user, **data).save()
    for user in users_old:
        membership = self.object.get_membership_for(user)
        membership.end_date = timezone.now()
        membership.save()
    return resp

ClubOldMembersView

Bases: ClubTabsMixin, CanViewMixin, DetailView

Old members of a club.

ClubSellingView

Bases: ClubTabsMixin, CanEditMixin, DetailFormView

Sellings of a club.

ClubSellingCSVView

Bases: ClubSellingView

Generate sellings in csv for a given period.

StreamWriter

Implements a file-like interface for streaming the CSV.

write(value)

Write the value by returning it, instead of storing in a buffer.

Source code in club/views.py
def write(self, value):
    """Write the value by returning it, instead of storing in a buffer."""
    return value

ClubEditView

Bases: ClubTabsMixin, CanEditMixin, UpdateView

Edit a Club.

Regular club board members will be able to edit the main infos (like the logo and the description). Admins will also be able to edit the club properties (like the name and the parent club).

ClubCreateView

Bases: PermissionRequiredMixin, CreateView

Create a club (for the Sith admin).

MembershipSetOldView

Bases: CanEditMixin, DetailView

Set a membership as beeing old.

MembershipDeleteView

Bases: PermissionRequiredMixin, DeleteView

Delete a membership (for admins only).

ClubMailingView

Bases: ClubTabsMixin, CanEditMixin, DetailFormView

A list of mailing for a given club.

add_new_mailing(cleaned_data)

Create a new mailing list from the form.

Source code in club/views.py
def add_new_mailing(self, cleaned_data) -> ValidationError | None:
    """Create a new mailing list from the form."""
    mailing = Mailing(
        club=self.object,
        email=cleaned_data["mailing_email"],
        moderator=self.request.user,
        is_moderated=False,
    )
    try:
        mailing.clean()
    except ValidationError as validation_error:
        return validation_error
    mailing.save()
    return None

add_new_subscription(cleaned_data)

Add mailing subscriptions for each user given and/or for the specified email in form.

Source code in club/views.py
def add_new_subscription(self, cleaned_data) -> ValidationError | None:
    """Add mailing subscriptions for each user given and/or for the specified email in form."""
    users_to_save = []

    for user in cleaned_data["subscription_users"]:
        sub = MailingSubscription(
            mailing=cleaned_data["subscription_mailing"], user=user
        )
        try:
            sub.clean()
        except ValidationError as validation_error:
            return validation_error

        sub.save()
        users_to_save.append(sub)

    if cleaned_data["subscription_email"]:
        sub = MailingSubscription(
            mailing=cleaned_data["subscription_mailing"],
            email=cleaned_data["subscription_email"],
        )

    try:
        sub.clean()
    except ValidationError as validation_error:
        return validation_error
    sub.save()

    # Save users after we are sure there is no error
    for user in users_to_save:
        user.save()

    return None

remove_subscription(cleaned_data)

Remove specified users from a mailing list.

Source code in club/views.py
def remove_subscription(self, cleaned_data):
    """Remove specified users from a mailing list."""
    fields = [
        val for key, val in cleaned_data.items() if key.startswith("removal_")
    ]
    for field in fields:
        for sub in field:
            sub.delete()

MailingDeleteView

Bases: CanEditMixin, DeleteView

MailingSubscriptionDeleteView

Bases: CanEditMixin, DeleteView

MailingAutoGenerationView

Bases: View

PosterListView

Bases: ClubTabsMixin, PosterListBaseView, CanViewMixin

List communication posters.

PosterCreateView

Bases: PosterCreateBaseView, CanCreateMixin

Create communication poster.

PosterEditView

Bases: ClubTabsMixin, PosterEditBaseView, CanEditMixin

Edit communication poster.

PosterDeleteView

Bases: PosterDeleteBaseView, ClubTabsMixin, CanEditMixin

Delete communication poster.