Code reference › models › event

class

Event

pretalx.event.models.event.Event source

Events are the central organising structure of pretalx models. The Event class has direct or indirect relations to all other models.

Fields 28

idAutoFieldpk
nameI18nCharFieldsource
name = I18nCharField(max_length=200, verbose_name=_("Name"))
slugSlugFielduniquesourceThe slug may only contain letters, numbers, dots and dashes.
slug = models.SlugField(
    max_length=50,
    db_index=True,
    unique=True,
    validators=[
        RegexValidator(
            regex=FULL_SLUG_REGEX, message=phrases.base.slug_validator_message
        ),
        validate_event_slug_permitted,
    ],
    verbose_name=_("Short form"),
    help_text=phrases.base.slug_validator_message,
)
organiserForeignKeynullOrganisersource
organiser = models.ForeignKey(
    to="Organiser",
    null=True,  # backwards compatibility, won’t ever be empty
    related_name="events",
    on_delete=models.PROTECT,
)
is_publicBooleanFieldsource
is_public = models.BooleanField(default=False, verbose_name=_("Event is public"))
date_fromDateFieldsource
date_from = DateField(verbose_name=_("Event start date"))
date_toDateFieldsource
date_to = DateField(verbose_name=_("Event end date"))
timezoneCharFieldsourceAll event dates will be localised and interpreted to be in this timezone.
timezone = models.CharField(
    choices=[(tz, timezone_name(tz)) for tz in TIMEZONE_CHOICES],
    max_length=32,
    default="UTC",
    help_text=_(
        "All event dates will be localised and interpreted to be in this timezone."
    ),
)
emailEmailFieldsourceWill be used as Reply-To in emails.
email = models.EmailField(
    verbose_name=_("Organiser email address"),
    help_text=_("Will be used as Reply-To in emails."),
)
custom_domainURLFieldnullsourceEnter a custom domain, such as https://my.event.example.org
custom_domain = models.URLField(
    verbose_name=_("Custom domain"),
    help_text=_("Enter a custom domain, such as https://my.event.example.org"),
    null=True,
    blank=True,
)
feature_flagsJSONFieldsource
feature_flags = models.JSONField(
    default=default_feature_flags, validators=[validate_feature_flags]
)
display_settingsJSONFieldsource
display_settings = models.JSONField(default=default_display_settings)
review_settingsJSONFieldsource
review_settings = models.JSONField(default=default_review_settings)
mail_settingsJSONFieldsource
mail_settings = models.JSONField(default=default_mail_settings)
attendee_signup_settingsJSONFieldsource
attendee_signup_settings = models.JSONField(
    default=default_attendee_signup_settings,
    validators=[validate_attendee_signup_settings],
)
primary_colorCharFieldnullsourceProvide a hex value like #00ff00 if you want to style pretalx in your event’s colour scheme.
primary_color = models.CharField(
    max_length=7,
    null=True,
    blank=True,
    validators=[RegexValidator("#([0-9A-Fa-f]{3}){1,2}")],
    verbose_name=_("Main event colour"),
    help_text=_(
        "Provide a hex value like #00ff00 if you want to style pretalx in your event’s colour scheme."
    ),
)
custom_cssFileFieldnullsourceUpload a custom CSS file if changing the primary colour is not sufficient for you.
custom_css = models.FileField(
    upload_to=event_css_path,
    null=True,
    blank=True,
    verbose_name=_("Custom Event CSS"),
    help_text=_(
        "Upload a custom CSS file if changing the primary colour is not sufficient for you."
    ),
)
header_imageImageFieldnullsourceIf you provide a header image, it will be displayed instead of your event’s color and/or header pattern at the top of all event pages. It will be center-aligned, so when the window shrinks, the center parts will continue to be displayed, and not stretched.
header_image = models.ImageField(
    upload_to=event_header_path,
    null=True,
    blank=True,
    verbose_name=_("Header image"),
    help_text=_(
        "If you provide a header image, it will be displayed instead of your event’s color and/or header pattern "
        "at the top of all event pages. It will be center-aligned, so when the window shrinks, the center parts will "
        "continue to be displayed, and not stretched."
    ),
)
og_imageImageFieldnullsourceThis image will be shown as a preview when links to your event are shared on social media or messaging apps. For best results, use an image at least 1200x630 pixels. If not set, the logo or header image will be used instead.
og_image = models.ImageField(
    upload_to=event_og_path,
    null=True,
    blank=True,
    verbose_name=_("Preview image"),
    help_text=_(
        "This image will be shown as a preview when links to your event are shared on "
        "social media or messaging apps. For best results, use an image at least 1200x630 pixels. "
        "If not set, the logo or header image will be used instead."
    ),
)
localesJSONFieldsource
locales = models.JSONField(default=default_locales)
content_localesJSONFieldsource
content_locales = models.JSONField(default=default_locales)
localeCharFieldsource
locale = models.CharField(
    max_length=32,
    default=settings.LANGUAGE_CODE,
    choices=settings.LANGUAGES,
    verbose_name=_("Default language"),
)
landing_page_textI18nTextFieldnullsourceThis text will be shown on the landing page, alongside with links to the CfP and schedule, if appropriate. You can use <a href="https://docs.pretalx.org/user/markdown/" target="_blank" rel="noopener">Markdown</a> here.
landing_page_text = I18nTextField(
    verbose_name=_("Landing page text"),
    help_text=format_lazy(
        "{} {}",
        _(
            "This text will be shown on the landing page, alongside with links to the CfP and schedule, if appropriate."
        ),
        phrases.base.use_markdown,
    ),
    null=True,
    blank=True,
)
pluginsTextFieldnullsource
plugins = models.TextField(null=True, blank=True, verbose_name=_("Plugins"))
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 21
log_entriesManyToOneRelActivityLog
_settings_objectsManyToOneRelEvent_SettingsStore
teamManyToManyRelTeam
queued_mailsManyToOneRelQueuedMail
mail_templatesManyToOneRelMailTemplate
attendee_profilesManyToOneRelAttendeeProfile
informationManyToOneRelSpeakerInformation
user_preferencesManyToOneRelUserEventPreferences
availabilitiesManyToOneRelAvailability
roomsManyToOneRelRoom
schedulesManyToOneRelSchedule
submitter_access_codesManyToOneRelSubmitterAccessCode
cfpOneToOneRelCfP
questionsManyToOneRelQuestion
score_categoriesManyToOneRelReviewScoreCategory
review_phasesManyToOneRelReviewPhase
submissionsManyToOneRelSubmission
tagsManyToOneRelTag
tracksManyToOneRelTrack
submission_typesManyToOneRelSubmissionType

Attributes 2

HEADER_PATTERN_CHOICES(('plain', 'Plain'), ('pcb', 'Circuits'), ('bubbles', 'Circles'), ('signal', 'Signal'), ('topo', 'Topography'), ('graph', 'Graph Paper'))
objects<pretalx.event.models.event.EventManager>
Inherited attributes 2
log_parentNoneLogMixin
log_prefixNoneLogMixin

Properties 33

Defined here

active_review_phasesource
@cached_property
def active_review_phase(self):
    return self.review_phases.filter(is_active=True).first()
available_content_localessource
@cached_property
def available_content_locales(self) -> list:
    # Content locales can be anything pretalx knows as a language, merged with
    # this event's plugin locales.

    locale_names = copy.copy(LANGUAGE_NAMES)
    locale_names.update(self.named_plugin_locales)
    return sorted([(key, value) for key, value in locale_names.items()])
available_pluginssource
@cached_property
def available_plugins(self):
    return {
        plugin.module: plugin
        for plugin in get_all_plugins(self)
        if not plugin.name.startswith(".") and getattr(plugin, "visible", True)
    }
cachesourceReturns an ObjectRelatedCache object.

This behaves equivalent to Django's built-in cache backends, but puts you into an isolated environment for this event, so you don't have to prefix your cache keys.

@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 event, so you
    don't have to prefix your cache keys.
    """
    return ObjectRelatedCache(self, field="slug")
cfp_flowsource
@cached_property
def cfp_flow(self):
    from pretalx.cfp.flow import CfPFlow  # noqa: PLC0415 -- circular import

    return CfPFlow(self)
current_schedulesource
@cached_property
def current_schedule(self):
    if pk := getattr(self, "_current_schedule_pk", None):
        # Annotated by the event middleware, saving the order-by query below
        return self.schedules.get(pk=pk)
    return (
        self.schedules.order_by("-published")
        .filter(published__isnull=False)
        .first()
    )
datetime_fromsourceThe localised datetime of the event start date.
@cached_property
def datetime_from(self) -> dt.datetime:
    """The localised datetime of the event start date."""
    return make_aware(
        dt.datetime.combine(self.date_from, dt.time(hour=0, minute=0, second=0)),
        self.tz,
    )
datetime_tosourceThe localised datetime of the event end date.
@cached_property
def datetime_to(self) -> dt.datetime:
    """The localised datetime of the event end date."""
    return make_aware(
        dt.datetime.combine(self.date_to, dt.time(hour=23, minute=59, second=59)),
        self.tz,
    )
durationsource
@cached_property
def duration(self):
    return (self.date_to - self.date_from).days + 1
eventsource
@cached_property
def event(self):
    return self
has_active_trackssource
@cached_property
def has_active_tracks(self) -> bool:
    return bool(self.get_feature_flag("use_tracks") and self.tracks.exists())
has_custom_stylessource
@cached_property
def has_custom_styles(self):
    return bool(
        self.primary_color
        or self.display_settings.get("heading_font")
        or self.display_settings.get("text_font")
        or self.custom_css
    )
has_unreleased_schedule_changessource
@cached_property
def has_unreleased_schedule_changes(self) -> bool:
    from pretalx.schedule.domain.changes import (  # noqa: PLC0415 -- thin method
        has_unreleased_schedule_changes,
    )

    return has_unreleased_schedule_changes(self)
is_multilingualsource
@cached_property
def is_multilingual(self) -> bool:
    return len(self.content_locales) > 1
named_content_localessource
@cached_property
def named_content_locales(self) -> list:
    locale_names = dict(self.available_content_locales)
    return [(code, locale_names[code]) for code in self.content_locales]
named_localessource
@cached_property
def named_locales(self) -> list:
    return [
        (language["code"], language["natural_name"])
        for language in settings.LANGUAGES_INFORMATION.values()
        if language["code"] in self.locales
    ]
named_plugin_localessource
@cached_property
def named_plugin_locales(self) -> list:
    locale_names = copy.copy(LANGUAGE_NAMES)
    locale_names.update(self.named_locales)
    result = {}
    for _receiver, locales in register_locales.send(sender=self):
        for locale in locales:
            if isinstance(locale, tuple):
                result[locale[0]] = locale[1]
            else:
                result[locale] = locale_names.get(locale, locale)
    return result
pending_mailssourceThe amount of currently unsent QueuedMail objects.
@cached_property
def pending_mails(self) -> int:
    """The amount of currently unsent :class:`~pretalx.mail.models.QueuedMail` objects."""
    return self.queued_mails.filter(state=QueuedMailStates.DRAFT).count()
plugin_listsource
@property
def plugin_list(self) -> list:
    if not self.plugins:
        return []
    return self.plugins.split(",")
plugin_localessource
@cached_property
def plugin_locales(self) -> list:
    return sorted(self.named_plugin_locales.keys())
primary_color_needs_dark_textsource
@cached_property
def primary_color_needs_dark_text(self):
    # If this property changes, the colourpicker.js preview for text
    # on primary colour buttons also needs to change.
    if not self.primary_color:
        return False

    return self.cache.get_or_set(
        f"dark_text_{self.primary_color.lstrip('#')}",
        lambda: not has_good_contrast(self.primary_color, threshold=3),
        timeout=86400 * 365,
    )
reviewerssource
@cached_property
def reviewers(self):
    from pretalx.person.models import User  # noqa: PLC0415 -- circular import

    return User.objects.filter(
        teams__in=self.teams.filter(is_reviewer=True)
    ).distinct()
reviewssource
@cached_property
def reviews(self):
    return Review.objects.filter(submission__event=self)
speakerssourceReturns a queryset of all speakers visible in the current released schedule.
@cached_property
def speakers(self):
    """Returns a queryset of all speakers visible in the current released schedule."""
    from pretalx.person.domain.queries.profile import (  # noqa: PLC0415 -- thin method
        speakers_for_event,
    )

    return speakers_for_event(self)
style_versionsource
@cached_property
def style_version(self):
    parts = (
        self.primary_color or "",
        self.display_settings.get("heading_font") or "",
        self.display_settings.get("text_font") or "",
        self.custom_css.name if self.custom_css else "",
    )
    return hashlib.md5(":".join(parts).encode()).hexdigest()[:8]  # noqa: S324 -- used for cache busting, not vulnerable to collision attacks
submitterssourceReturns a queryset of all speakers with submissions.
@cached_property
def submitters(self):
    """Returns a queryset of all speakers with submissions."""
    from pretalx.person.domain.queries.profile import (  # noqa: PLC0415 -- thin method
        submitters_for_event,
    )

    return submitters_for_event(self)
talkssourceReturns a queryset of all Submission objects in the current released schedule.
@cached_property
def talks(self):
    """Returns a queryset of all :class:`~pretalx.submission.models.submission.Submission`
    objects in the current released schedule."""
    from pretalx.submission.domain.queries.submission import (  # noqa: PLC0415 -- thin method
        talks_for_event,
    )

    return talks_for_event(self)
teamssource
@cached_property
def teams(self):
    from pretalx.event.models.organiser import (  # noqa: PLC0415 -- circular import
        Team,
    )

    return (
        Team.objects.select_related("organiser")
        .filter(organiser_id=self.organiser_id)
        .filter(
            models.Q(all_events=True)
            | models.Q(models.Q(all_events=False) & models.Q(limit_events=self))
        )
        .distinct()
    )
tzsource
@cached_property
def tz(self):
    return zoneinfo.ZoneInfo(self.timezone)
valid_availabilitiessource
@property
def valid_availabilities(self):
    return self.availabilities.filter(
        start__lte=self.datetime_to, end__gte=self.datetime_from
    )
visible_primary_colorsource
@cached_property
def visible_primary_color(self):
    return self.primary_color or settings.DEFAULT_EVENT_PRIMARY_COLOR
wip_schedulesource
@cached_property
def wip_schedule(self):
    try:
        schedule, _ = self.schedules.get_or_create(version__isnull=True)
    except MultipleObjectsReturned:
        # No idea how this happens – a race condition due to transaction weirdness?
        schedules = list(self.schedules.filter(version__isnull=True))
        schedule = schedules[0]
        # It's only ever been two so far, but while we're being resilient …
        for dupe in schedules[1:]:
            TalkSlot.objects.filter(schedule=dupe).delete()
            dupe.delete()
    return schedule

Added at runtime

Added by Django or another library dynamically after class creation.
settings

Methods 39

Defined here

clean()sourceHook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields.

on pretalx.event.models.event.Event source

Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS.

def clean(self):
    super().clean()
    if self.slug:
        self.slug = self.slug.lower()
    validate_event_slug_unique(
        self.slug, exclude_event=None if self._state.adding else self
    )
    if self.date_from and self.date_to and self.date_from > self.date_to:
        raise ValidationError({"date_from": phrases.orga.event_date_start_invalid})
    if self.locale and self.locales and self.locale not in self.locales:
        raise ValidationError(
            {
                "locale": _(
                    "Your default language needs to be one of your active languages."
                )
            }
        )

on django.db.models.Model

Hook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS.

def clean(self):
    """
    Hook for doing any extra model-wide validation after clean() has been
    called on every field by self.clean_fields. Any ValidationError raised
    by this method will not be associated with a particular field; it will
    have a special-case association with the field defined by
    NON_FIELD_ERRORS.
    """
    pass
get_date_range_display() -> strsourceReturns the localised, prettily formatted date range for this event.
def get_date_range_display(self) -> str:
    """Returns the localised, prettily formatted date range for this event."""
    return daterange(self.date_from, self.date_to)
get_feature_flag(feature)source
def get_feature_flag(self, feature):
    if feature in self.feature_flags:
        return self.feature_flags[feature]
    return default_feature_flags().get(feature, False)
__str__() -> strsourceReturn str(self).

on pretalx.event.models.event.Event source

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

on django.db.models.Model

Return str(self).

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

From LogMixin pretalx.common.models.mixins

delete(*args, log_kwargs=None, skip_log=False, **kwargs)source

on pretalx.common.models.mixins.LogMixin source

def delete(self, *args, log_kwargs=None, skip_log=False, **kwargs):
    parent = self.log_parent
    result = super().delete(*args, **kwargs)
    if (
        not skip_log
        and parent
        and getattr(parent, "log_action", None)
        and self.log_prefix
    ):
        log_kwargs = log_kwargs or {}
        parent.log_action(f"{self.log_prefix}.delete", **log_kwargs)
    return result

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()
get_instance_data()sourceGet a dictionary of field values for this instance.

Used for change tracking in log_action. Excludes auto-updated fields like timestamps and sensitive data. Does not handle many-to-many fields.

def get_instance_data(self):
    """Get a dictionary of field values for this instance.

    Used for change tracking in log_action. Excludes auto-updated
    fields like timestamps and sensitive data.
    Does not handle many-to-many fields.
    """
    excluded_fields = {
        "created",
        "updated",
        "is_active",
        "last_login",
        "user",
        "event",
        "code",
    }
    data = {}

    for field in self._meta.fields:
        if (
            field.name in excluded_fields
            or field.name in SENSITIVE_KEYS
            or "thumbnail" in field.name
            or getattr(field, "auto_now", False)
            or getattr(field, "auto_now_add", False)
        ):
            continue

        if isinstance(field, models.ForeignKey):
            data[field.name] = getattr(self, field.attname, None)
            continue

        value = getattr(self, field.name, None)

        if isinstance(field, models.FileField):
            data[field.name] = value.name if value else None
        elif isinstance(field, models.UUIDField):
            data[field.name] = str(value) if value else None
        elif isinstance(value, LazyI18nString):
            if isinstance(getattr(value, "data", None), dict):
                data[field.name] = {k: v for k, v in value.data.items() if v}
            else:
                data[field.name] = str(value)
        else:
            data[field.name] = json_roundtrip(value)
    return data
log_action(action, data=None, person=None, orga=False, content_object=None, old_data=None, new_data=None)source
def log_action(
    self,
    action,
    data=None,
    person=None,
    orga=False,
    content_object=None,
    old_data=None,
    new_data=None,
):
    if self._state.adding or not isinstance(self.pk, int):
        return

    if action.startswith("."):
        if self.log_prefix:
            action = f"{self.log_prefix}{action}"
        else:
            return

    if old_data is not None or new_data is not None:
        from pretalx.common.log import (  # noqa: PLC0415 -- thin method
            compute_log_changes,
        )

        changes = compute_log_changes(old_data, new_data)
        if not changes and not data:
            return
        if changes:
            if data is None:
                data = {}
            data["changes"] = changes

    if data:
        if not isinstance(data, dict):
            raise TypeError(
                f"Logged data should always be a dictionary, not {type(data)}."
            )
        for key in data:
            if any(sensitive_key in key for sensitive_key in SENSITIVE_KEYS):
                data[key] = "********" if data[key] else data[key]
        data = json_roundtrip(data)

    return ActivityLog.objects.create(
        person=person,
        content_object=content_object or self,
        action_type=action,
        data=data,
        is_orga_action=orga,
        **self._log_event_kwargs(),
    )
logged_actions()source
def logged_actions(self):
    return (
        ActivityLog.objects.filter(
            content_type=ContentType.objects.get_for_model(type(self)),
            object_id=self.pk,
        )
        .select_related("event", "person")
        .prefetch_related("content_object")
    )

From FileCleanupMixin pretalx.common.models.mixins

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(), adelete(), arefresh_from_db() and 19 more.
adeletearefresh_from_dbasaveclean_fieldsdate_error_messagefull_cleanget_constraintsget_deferred_fieldsprepare_database_saverefresh_from_dbsave_baseserializable_valueunique_error_messagevalidate_constraintsvalidate_unique__eq____getstate____hash____init____reduce____repr____setstate__

Added at runtime

Added by Django or another library dynamically after class creation.
get_locale_displayget_next_by_date_fromget_next_by_date_toget_previous_by_date_fromget_previous_by_date_toget_timezone_display