Code reference › models › person

class

ProfilePicture

pretalx.person.models.picture.ProfilePicture source

Stores profile pictures belonging to a user acccount and/or speaker profile.

Users owning a ProfilePicture object can re-use it across events.

Fields 7

idAutoFieldpk
userForeignKeynullUsersource
user = models.ForeignKey(
    to="person.User",
    related_name="pictures",
    on_delete=models.CASCADE,
    null=True,
    blank=True,
)
avatarImageFieldnullsource
avatar = models.ImageField(
    null=True, blank=True, verbose_name=_("Profile picture"), upload_to=picture_path
)
avatar_thumbnailImageFieldnullsource
avatar_thumbnail = models.ImageField(null=True, blank=True, upload_to="avatars/")
avatar_thumbnail_tinyImageFieldnullsource
avatar_thumbnail_tiny = models.ImageField(
    null=True, blank=True, upload_to="avatars/"
)
createdDateTimeFieldnullTimestampedModelsource

on pretalx.common.models.mixins.TimestampedModel source

created = models.DateTimeField(
    verbose_name=_("Created"), auto_now_add=True, blank=True, null=True
)
updatedDateTimeFieldnullTimestampedModelsource

on pretalx.common.models.mixins.TimestampedModel source

updated = models.DateTimeField(
    verbose_name=_("Updated"), auto_now=True, blank=True, null=True
)
Reverse relations 2
speakersManyToOneRelSpeakerProfile
usersManyToOneRelUser

Attributes 1

objects<pretalx.common.models.managers.PretalxManager>

Properties 2

Defined here

avatar_urlsource
@cached_property
def avatar_url(self):
    if self.has_avatar:
        return self.avatar.url
has_avatarsource
@cached_property
def has_avatar(self):
    return bool(self.avatar) and self.avatar != "False"

Methods 29

Defined here

get_avatar_url(event=None, thumbnail=None)source
def get_avatar_url(self, event=None, thumbnail=None):
    from pretalx.common.image import (  # noqa: PLC0415 -- thin method
        THUMBNAIL_SIZES,
        queue_thumbnail_regeneration,
    )

    if not self.avatar_url:
        return ""
    if not thumbnail:
        image = self.avatar
    else:
        if thumbnail not in THUMBNAIL_SIZES:
            return None
        image = (
            self.avatar_thumbnail_tiny
            if thumbnail == "tiny"
            else self.avatar_thumbnail
        )
        if not image:
            queue_thumbnail_regeneration(self.avatar)
            image = self.avatar
    if event and event.custom_domain:
        return urljoin(event.custom_domain, image.url)
    return urljoin(settings.SITE_URL, image.url)
__str__()sourceReturn str(self).

on pretalx.person.models.picture.ProfilePicture source

def __str__(self):
    return f"ProfilePicture(user={self.user.code if self.user else None})"

on django.db.models.Model

Return str(self).

def __str__(self):
    return "%s object (%s)" % (self.__class__.__name__, self.pk)

From FileCleanupMixin pretalx.common.models.mixins

delete(*args, **kwargs)source

on pretalx.common.models.mixins.FileCleanupMixin source

def delete(self, *args, **kwargs):
    self.delete_files()
    return super().delete(*args, **kwargs)

on django.db.models.Model

def delete(self, using=None, keep_parents=False):
    if not self._is_pk_set():
        raise ValueError(
            "%s object can't be deleted because its %s attribute is set "
            "to None." % (self._meta.object_name, self._meta.pk.attname)
        )
    using = using or router.db_for_write(self.__class__, instance=self)
    collector = Collector(using=using, origin=self)
    collector.collect([self], keep_parents=keep_parents)
    return collector.delete()
delete_files()sourceSchedule cleanup of every uploaded file attached to this object.

Public hook: called by delete() and by anonymisation paths (e.g. person.domain.user.deactivate_user) that want to drop files without removing the row. Overridable by subclasses that need to recurse into related objects.

def delete_files(self):
    """Schedule cleanup of every uploaded file attached to this object.

    Public hook: called by ``delete()`` and by anonymisation paths
    (e.g. ``person.domain.user.deactivate_user``) that want to drop
    files without removing the row. Overridable by subclasses that
    need to recurse into related objects."""
    for field in self._file_fields:
        value = getattr(self, field, None)
        if not value:
            continue
        with suppress(Exception):
            self._schedule_file_cleanup(field=field, path=value.path)
process_image(field, generate_thumbnail=False)source
def process_image(self, field, generate_thumbnail=False):
    task_process_image.apply_async(
        kwargs={
            "field": field,
            "model": self._meta.model_name.capitalize(),
            "pk": self.pk,
            "generate_thumbnail": generate_thumbnail,
        },
        countdown=10,
    )
save(*args, **kwargs)source

on pretalx.common.models.mixins.FileCleanupMixin source

def save(self, *args, **kwargs):
    update_fields = kwargs.get("update_fields")
    if self._state.adding or (
        update_fields and not set(self._file_fields) & set(update_fields)
    ):
        return super().save(*args, **kwargs)

    try:
        pre_save_instance = self.__class__.objects.get(pk=self.pk)
    except ObjectDoesNotExist:
        return super().save(*args, **kwargs)

    old_files = {}
    for field in self._file_fields:
        if old_value := getattr(pre_save_instance, field):
            new_value = getattr(self, field)
            if new_value and old_value.path != new_value.path:
                old_files[field] = old_value.path

    result = super().save(*args, **kwargs)
    for field, path in old_files.items():
        self._schedule_file_cleanup(field=field, path=path)
    return result

on django.db.models.Model

Save the current instance. Override this in a subclass if you want to control the saving process.

The 'force_insert' and 'force_update' parameters can be used to insist that the "save" must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set.

def save(
    self,
    *,
    force_insert=False,
    force_update=False,
    using=None,
    update_fields=None,
):
    """
    Save the current instance. Override this in a subclass if you want to
    control the saving process.

    The 'force_insert' and 'force_update' parameters can be used to insist
    that the "save" must be an SQL insert or update (or equivalent for
    non-SQL backends), respectively. Normally, they should not be set.
    """

    self._prepare_related_fields_for_save(operation_name="save")

    using = using or router.db_for_write(self.__class__, instance=self)
    if force_insert and (force_update or update_fields):
        raise ValueError("Cannot force both insert and updating in model saving.")

    deferred_non_generated_fields = {
        f.attname
        for f in self._meta.concrete_fields
        if f.attname not in self.__dict__ and f.generated is False
    }
    if update_fields is not None:
        # If update_fields is empty, skip the save. We do also check for
        # no-op saves later on for inheritance cases. This bailout is
        # still needed for skipping signal sending.
        if not update_fields:
            return

        update_fields = frozenset(update_fields)
        field_names = self._meta._non_pk_concrete_field_names
        not_updatable_fields = update_fields.difference(field_names)

        if not_updatable_fields:
            raise ValueError(
                "The following fields do not exist in this model, are m2m "
                "fields, primary keys, or are non-concrete fields: %s"
                % ", ".join(not_updatable_fields)
            )

    # If saving to the same database, and this model is deferred, then
    # automatically do an "update_fields" save on the loaded fields.
    elif (
        not force_insert
        and deferred_non_generated_fields
        and using == self._state.db
        and self._is_pk_set()
    ):
        field_names = set()
        pk_fields = self._meta.pk_fields
        for field in self._meta.concrete_fields:
            if field not in pk_fields and not hasattr(field, "through"):
                field_names.add(field.attname)
        loaded_fields = field_names.difference(deferred_non_generated_fields)
        if loaded_fields:
            update_fields = frozenset(loaded_fields)

    self.save_base(
        using=using,
        force_insert=force_insert,
        force_update=force_update,
        update_fields=update_fields,
    )

From Model django.db.models

Standard Django API, unchanged — full_clean(), clean(), adelete() and 20 more.
adeletearefresh_from_dbasavecleanclean_fieldsdate_error_messagefull_cleanget_constraintsget_deferred_fieldsprepare_database_saverefresh_from_dbsave_baseserializable_valueunique_error_messagevalidate_constraintsvalidate_unique__eq____getstate____hash____init____reduce____repr____setstate__