Aller au contenu

Views

ClubEditForm(*args, **kwargs)

Bases: ModelForm

Source code in club/forms.py
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields["short_description"].widget = forms.Textarea()

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.filter(end_date=None).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_id in cleaned_data["users"]:
        user = User.objects.filter(id=user_id).first()
        if not user:
            raise forms.ValidationError(
                _("One of the selected users doesn't exist"), code="invalid"
            )
        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"]:
        user = User.objects.filter(id=user).first()
        if not user:
            raise forms.ValidationError(
                _("One of the selected users doesn't exist"), code="invalid"
            )
        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.

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):
    """Method to see if that object can be super edited by the given user."""
    if user.is_anonymous:
        return False
    return 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):
    """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):
    """Method to see if that object can be seen by the given user."""
    sub = User.objects.filter(pk=user.pk).first()
    if sub is None:
        return False
    return sub.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):
    """Method to see if that object can be super edited by the given user."""
    if user.is_anonymous:
        return False
    return 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)
    if membership is not None and membership.role >= self.role:
        return True
    return False

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.get_object(), user=user, **data).save()
    for user in users_old:
        membership = self.get_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's main informations (for the club's members).

ClubEditPropView

Bases: ClubTabsMixin, CanEditPropMixin, UpdateView

Edit the properties of a Club object (for the Sith admins).

ClubCreateView

Bases: CanCreateMixin, CreateView

Create a club (for the Sith admin).

MembershipSetOldView

Bases: CanEditMixin, DetailView

Set a membership as beeing old.

MembershipDeleteView

Bases: UserIsRootMixin, DeleteView

Delete a membership (for admins only).

ClubStatView

Bases: TemplateView

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.get_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 = [
        cleaned_data[key]
        for key in cleaned_data.keys()
        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.