Exemple #1
0
class Organizer(LoggedModel):
    """
    This model represents an entity organizing events, e.g. a company, institution,
    charity, person, …

    :param name: The organizer's name
    :type name: str
    :param slug: A globally unique, short name for this organizer, to be used
                 in URLs and similar places.
    :type slug: str
    """

    settings_namespace = 'organizer'
    name = models.CharField(max_length=200, verbose_name=_("Name"))
    slug = models.SlugField(
        max_length=50,
        db_index=True,
        help_text=
        _("Should be short, only contain lowercase letters, numbers, dots, and dashes. Every slug can only be used "
          "once. This is being used in URLs to refer to your organizer accounts and your events."
          ),
        validators=[
            RegexValidator(
                regex="^[a-zA-Z0-9][a-zA-Z0-9.-]+$",
                message=
                _("The slug may only contain letters, numbers, dots and dashes."
                  )),
            OrganizerSlugBanlistValidator()
        ],
        verbose_name=_("Short form"),
        unique=True)

    class Meta:
        verbose_name = _("Organizer")
        verbose_name_plural = _("Organizers")
        ordering = ("name", )

    def __str__(self) -> str:
        return self.name

    def save(self, *args, **kwargs):
        obj = super().save(*args, **kwargs)
        self.get_cache().clear()
        return obj

    def get_cache(self):
        """
        Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to
        Django's built-in cache backends, but puts you into an isolated environment for
        this organizer, so you don't have to prefix your cache keys. In addition, the cache
        is being cleared every time the organizer changes.

        .. deprecated:: 1.9
           Use the property ``cache`` instead.
        """
        return self.cache

    @cached_property
    def cache(self):
        """
        Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to
        Django's built-in cache backends, but puts you into an isolated environment for
        this organizer, so you don't have to prefix your cache keys. In addition, the cache
        is being cleared every time the organizer changes.
        """
        from pretix.base.cache import ObjectRelatedCache

        return ObjectRelatedCache(self)

    @property
    def has_gift_cards(self):
        return self.cache.get_or_set(
            key='has_gift_cards',
            timeout=15,
            default=lambda: self.issued_gift_cards.exists(
            ) or self.gift_card_issuer_acceptance.exists())

    @property
    def accepted_gift_cards(self):
        from .giftcards import GiftCard, GiftCardAcceptance

        return GiftCard.objects.annotate(accepted=Exists(
            GiftCardAcceptance.objects.filter(
                issuer=OuterRef('issuer'), collector=self))).filter(
                    Q(issuer=self) | Q(accepted=True))

    def allow_delete(self):
        from . import Order, Invoice
        return (not Order.objects.filter(event__organizer=self).exists()
                and not Invoice.objects.filter(event__organizer=self).exists()
                and not self.devices.exists())

    def delete_sub_objects(self):
        for e in self.events.all():
            e.delete_sub_objects()
            e.delete()
        self.teams.all().delete()
Exemple #2
0
class Organizer(LoggedModel):
    """
    This model represents an entity organizing events, e.g. a company, institution,
    charity, person, …

    :param name: The organizer's name
    :type name: str
    :param slug: A globally unique, short name for this organizer, to be used
                 in URLs and similar places.
    :type slug: str
    """

    settings_namespace = 'organizer'
    name = models.CharField(max_length=200,
                            verbose_name=_("Name"))
    slug = models.CharField(
        max_length=50, db_index=True,
        help_text=_(
            "Should be short, only contain lowercase letters, numbers, dots, and dashes. Every slug can only be used "
            "once. This is being used in URLs to refer to your organizer accounts and your events."),
        validators=[
            MinLengthValidator(
                limit_value=2,
            ),
            RegexValidator(
                regex="^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$",
                message=_("The slug may only contain letters, numbers, dots and dashes.")
            ),
            OrganizerSlugBanlistValidator()
        ],
        verbose_name=_("Short form"),
        unique=True
    )

    class Meta:
        verbose_name = _("Organizer")
        verbose_name_plural = _("Organizers")
        ordering = ("name",)

    def __str__(self) -> str:
        return self.name

    def save(self, *args, **kwargs):
        is_new = not self.pk
        obj = super().save(*args, **kwargs)
        if is_new:
            self.set_defaults()
        else:
            self.get_cache().clear()
        return obj

    def set_defaults(self):
        """
        This will be called after organizer creation.
        This way, we can use this to introduce new default settings to pretix that do not affect existing organizers.
        """
        self.settings.cookie_consent = True

    def get_cache(self):
        """
        Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to
        Django's built-in cache backends, but puts you into an isolated environment for
        this organizer, so you don't have to prefix your cache keys. In addition, the cache
        is being cleared every time the organizer changes.

        .. deprecated:: 1.9
           Use the property ``cache`` instead.
        """
        return self.cache

    @cached_property
    def cache(self):
        """
        Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to
        Django's built-in cache backends, but puts you into an isolated environment for
        this organizer, so you don't have to prefix your cache keys. In addition, the cache
        is being cleared every time the organizer changes.
        """
        from pretix.base.cache import ObjectRelatedCache

        return ObjectRelatedCache(self)

    @property
    def timezone(self):
        return pytz.timezone(self.settings.timezone)

    @cached_property
    def all_logentries_link(self):
        return reverse(
            'control:organizer.log',
            kwargs={
                'organizer': self.slug,
            }
        )

    @property
    def has_gift_cards(self):
        return self.cache.get_or_set(
            key='has_gift_cards',
            timeout=15,
            default=lambda: self.issued_gift_cards.exists() or self.gift_card_issuer_acceptance.exists()
        )

    @property
    def accepted_gift_cards(self):
        from .giftcards import GiftCard, GiftCardAcceptance

        return GiftCard.objects.annotate(
            accepted=Exists(GiftCardAcceptance.objects.filter(issuer=OuterRef('issuer'), collector=self))
        ).filter(
            Q(issuer=self) | Q(accepted=True)
        )

    @property
    def default_gift_card_expiry(self):
        if self.settings.giftcard_expiry_years is not None:
            tz = get_current_timezone()
            return make_aware(datetime.combine(
                date(now().astimezone(tz).year + self.settings.get('giftcard_expiry_years', as_type=int), 12, 31),
                time(hour=23, minute=59, second=59)
            ), tz)

    def allow_delete(self):
        from . import Invoice, Order
        return (
            not Order.objects.filter(event__organizer=self).exists() and
            not Invoice.objects.filter(event__organizer=self).exists() and
            not self.devices.exists()
        )

    def delete_sub_objects(self):
        for e in self.events.all():
            e.delete_sub_objects()
            e.delete()
        self.teams.all().delete()

    def get_mail_backend(self, timeout=None):
        """
        Returns an email server connection, either by using the system-wide connection
        or by returning a custom one based on the organizer's settings.
        """
        if self.settings.smtp_use_custom:
            return get_connection(backend=settings.EMAIL_CUSTOM_SMTP_BACKEND,
                                  host=self.settings.smtp_host,
                                  port=self.settings.smtp_port,
                                  username=self.settings.smtp_username,
                                  password=self.settings.smtp_password,
                                  use_tls=self.settings.smtp_use_tls,
                                  use_ssl=self.settings.smtp_use_ssl,
                                  fail_silently=False, timeout=timeout)
        else:
            return get_connection(fail_silently=False)