# versions.Version

## Model Info

| Key | Value |
|---|-----|
| Model Name | Version |
| Verbose Name | version |
| Verbose Name Plural | versions |
| Docstring | <p>A version is a unique iteration of an add-on.<br>Versions are created for a specific channel and<br>relate to a specific uploaded XPI file.</p> |
| Is Abstract | False |
| Is Proxy | False |
| Is Managed | True |
| Ordering | ['-created', '-modified'] |
| Permissions | [] |
| Default Permissions | ('add', 'change', 'delete', 'view') |
| Indexes | [<Index: fields=['addon'] name='addon_id'>, <Index: fields=['license'] name='license_id'>, <Index: fields=['due_date'] name='versions_due_date_b9c73ed7'>] |
| Constraints | [<UniqueConstraint: fields=('addon', 'version') name='versions_addon_id_version_5a2e75b6_uniq'>] |
| Database Table | versions |
| Base Manager | unfiltered |
| Default Manager | None |
| File | /data/olympia/src/olympia/versions/models.py |
| Starting Line Number | 285 |
| Method Resolution Order | (<class 'olympia.versions.models.Version'>, <class 'olympia.amo.models.OnChangeMixin'>, <class 'olympia.amo.models.ModelBase'>, <class 'olympia.amo.models.SaveUpdateMixin'>, <class 'django.db.models.base.Model'>, <class 'django.db.models.utils.AltersData'>, <class 'object'>) |

## Fields

| Field Name | Field Type | Database Column | Database Type | Verbose Name |
|----------|----------|---------------|-------------|------------|
| `+` | ManyToOneRel |  | integer UNSIGNED |  |
| `ContentDecision_target_versions+` | ManyToOneRel |  | integer UNSIGNED |  |
| `addon` | ForeignKey | addon_id | integer UNSIGNED | addon |
| `approval_notes` | TextField | approvalnotes | longtext | approval notes |
| `apps` | ManyToOneRel |  | integer UNSIGNED |  |
| `autoapprovalsummary` | OneToOneRel |  | integer UNSIGNED |  |
| `blockversion` | OneToOneRel |  | integer UNSIGNED |  |
| `channel` | IntegerField | channel | integer | channel |
| `contentdecision` | ManyToManyRel |  | through abuse.ContentDecision_target_versions |  |
| `created` | DateTimeField | created | datetime(6) | created |
| `deleted` | BooleanField | deleted | bool | deleted |
| `draftcomment` | ManyToOneRel |  | integer UNSIGNED |  |
| `due_date` | DateTimeField | due_date | datetime(6) | due date |
| `file` | OneToOneRel |  | integer UNSIGNED |  |
| `git_hash` | CharField | git_hash | varchar(40) | git hash |
| `human_review_date` | DateTimeField | human_review_date | datetime(6) | human review date |
| `id (pk)` | PositiveAutoField | id | integer UNSIGNED AUTO_INCREMENT | id |
| `installorigin` | ManyToOneRel |  | integer UNSIGNED |  |
| `license` | ForeignKey | license_id | integer UNSIGNED | license |
| `modified` | DateTimeField | modified | datetime(6) | modified |
| `needshumanreview` | ManyToOneRel |  | integer UNSIGNED |  |
| `previews` | ManyToOneRel |  | integer UNSIGNED |  |
| `promoted_versions` | ManyToOneRel |  | integer UNSIGNED |  |
| `ratings` | ManyToOneRel |  | integer UNSIGNED |  |
| `release_notes` | PurifiedMarkdownField | releasenotes | integer UNSIGNED | release notes |
| `reviewerflags` | OneToOneRel |  | integer UNSIGNED |  |
| `reviewqueuehistory` | ManyToOneRel |  | integer UNSIGNED |  |
| `scannerqueryresults` | ManyToOneRel |  | integer UNSIGNED |  |
| `scannerresults` | ManyToOneRel |  | integer UNSIGNED |  |
| `source` | FileField | source | varchar(255) | source |
| `token` | ManyToOneRel |  | integer UNSIGNED |  |
| `version` | VersionStringField | version | varchar(255) | version |
| `versionlog` | ManyToOneRel |  | integer UNSIGNED |  |
| `versionprovenance` | ManyToOneRel |  | integer UNSIGNED |  |

## Relations

| Field Name | Field Type | Database Column | Database Type | Related Model | Related Name |
|----------|----------|---------------|-------------|-------------|------------|
| `addon` | ForeignKey | addon_id | integer UNSIGNED | addons.Addon | versions |
| `license` | ForeignKey | license_id | integer UNSIGNED | versions.License | version_set |
| `release_notes` | PurifiedMarkdownField | releasenotes | integer UNSIGNED | translations.PurifiedMarkdownTranslation | Version_release_notes_set+ |

fields_reverse_relation=[FieldReverseRelation(name='ContentDecision_target_versions+ (no reverse relation allowed)', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='abuse.ContentDecision_target_versions', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='ManyToManyRel', field_db_type='through abuse.ContentDecision_target_versions', related_model='abuse.ContentDecision', field_name_on_related_model='target_versions', field_type_on_related_model='ManyToManyField'), FieldReverseRelation(name='token', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='activity.ActivityLogToken', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='activity.VersionLog', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='activity.DraftComment', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='+ (no reverse relation allowed)', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='addons.Addon', field_name_on_related_model='_current_version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='OneToOneRel', field_db_type='integer UNSIGNED', related_model='blocklist.BlockVersion', field_name_on_related_model='version', field_type_on_related_model='OneToOneField'), FieldReverseRelation(name='version_set', field_type='OneToOneRel', field_db_type='integer UNSIGNED', related_model='files.File', field_name_on_related_model='version', field_type_on_related_model='OneToOneField'), FieldReverseRelation(name='promoted_versions', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='promoted.PromotedApproval', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='ratings', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='ratings.Rating', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='OneToOneRel', field_db_type='integer UNSIGNED', related_model='reviewers.AutoApprovalSummary', field_name_on_related_model='version', field_type_on_related_model='OneToOneField'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='reviewers.NeedsHumanReview', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='reviewers.ReviewQueueHistory', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='scannerresults', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='scanners.ScannerResult', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='scannerqueryresults', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='scanners.ScannerQueryResult', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='reviewerflags', field_type='OneToOneRel', field_db_type='integer UNSIGNED', related_model='versions.VersionReviewerFlags', field_name_on_related_model='version', field_type_on_related_model='OneToOneField'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='versions.VersionProvenance', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='previews', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='versions.VersionPreview', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='apps', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='versions.ApplicationsVersions', field_name_on_related_model='version', field_type_on_related_model='ForeignKey'), FieldReverseRelation(name='version_set', field_type='ManyToOneRel', field_db_type='integer UNSIGNED', related_model='versions.InstallOrigin', field_name_on_related_model='version', field_type_on_related_model='ForeignKey')]

## Reverse Relations

| Field Name | Field Type | Database Type | Related Model | Field Name on Related Model | Field Type on Related Model |
|----------|----------|-------------|-------------|---------------------------|---------------------------|
| `+ (no reverse relation allowed)` | ManyToOneRel | integer UNSIGNED | addons.Addon | _current_version | ForeignKey |
| `ContentDecision_target_versions+ (no reverse relation allowed)` | ManyToOneRel | integer UNSIGNED | abuse.ContentDecision_target_versions | version | ForeignKey |
| `apps` | ManyToOneRel | integer UNSIGNED | versions.ApplicationsVersions | version | ForeignKey |
| `previews` | ManyToOneRel | integer UNSIGNED | versions.VersionPreview | version | ForeignKey |
| `promoted_versions` | ManyToOneRel | integer UNSIGNED | promoted.PromotedApproval | version | ForeignKey |
| `ratings` | ManyToOneRel | integer UNSIGNED | ratings.Rating | version | ForeignKey |
| `reviewerflags` | OneToOneRel | integer UNSIGNED | versions.VersionReviewerFlags | version | OneToOneField |
| `scannerqueryresults` | ManyToOneRel | integer UNSIGNED | scanners.ScannerQueryResult | version | ForeignKey |
| `scannerresults` | ManyToOneRel | integer UNSIGNED | scanners.ScannerResult | version | ForeignKey |
| `token` | ManyToOneRel | integer UNSIGNED | activity.ActivityLogToken | version | ForeignKey |
| `version_set` | ManyToManyRel | through abuse.ContentDecision_target_versions | abuse.ContentDecision | target_versions | ManyToManyField |
| `version_set` | ManyToOneRel | integer UNSIGNED | activity.VersionLog | version | ForeignKey |
| `version_set` | ManyToOneRel | integer UNSIGNED | activity.DraftComment | version | ForeignKey |
| `version_set` | OneToOneRel | integer UNSIGNED | blocklist.BlockVersion | version | OneToOneField |
| `version_set` | OneToOneRel | integer UNSIGNED | files.File | version | OneToOneField |
| `version_set` | OneToOneRel | integer UNSIGNED | reviewers.AutoApprovalSummary | version | OneToOneField |
| `version_set` | ManyToOneRel | integer UNSIGNED | reviewers.NeedsHumanReview | version | ForeignKey |
| `version_set` | ManyToOneRel | integer UNSIGNED | reviewers.ReviewQueueHistory | version | ForeignKey |
| `version_set` | ManyToOneRel | integer UNSIGNED | versions.VersionProvenance | version | ForeignKey |
| `version_set` | ManyToOneRel | integer UNSIGNED | versions.InstallOrigin | version | ForeignKey |

## Methods

### Other Methods

| Method Name | Signature |
|-----------|---------|
| `can_be_disabled_and_deleted` | `(self)` |
| `disable_old_files` | `(self)` |
| `flag_if_sources_were_provided` | `(self, user)` |
| `from_upload` | `(upload, addon, channel, *, selected_apps=None, compatibility=None, parsed_data=None, client_info=None)` |
| `generate_due_date` | `(self)` |
| `get_admin_absolute_url` | `(self)` |
| `get_admin_url_path` | `(self)` |
| `get_background_images_encoded` | `(self, header_only=False)` |
| `get_channel_display` | `(self, *, field=<django.db.models.fields.IntegerField: channel>)` |
| `get_next_by_created` | `(self, *, field=<django.db.models.fields.DateTimeField: created>, is_next=True, **kwargs)` |
| `get_next_by_modified` | `(self, *, field=<django.db.models.fields.DateTimeField: modified>, is_next=True, **kwargs)` |
| `get_previous_by_created` | `(self, *, field=<django.db.models.fields.DateTimeField: created>, is_next=False, **kwargs)` |
| `get_previous_by_modified` | `(self, *, field=<django.db.models.fields.DateTimeField: modified>, is_next=False, **kwargs)` |
| `get_review_status_display` | `(self, show_auto_approval_and_delay_reject=False)` |
| `get_review_status_for_auto_approval_and_delay_reject` | `(self)` |
| `get_unfiltered_manager` | `()` |
| `get_url_path` | `(self)` |
| `is_public` | `(self)` |
| `on_change` | `(callback)` |
| `reload` | `(self)` |
| `reset_due_date` | `(self, due_date=None, should_have_due_date=None)` |
| `serializable_reference` | `(self)` |
| `set_compatible_apps` | `(self, apps)` |
| `transformer` | `(versions)` |
| `transformer_activity` | `(versions)` |
| `transformer_auto_approvable` | `(versions)` |
| `transformer_license` | `(versions)` |
| `transformer_promoted` | `(versions)` |
| `update` | `(self, **kwargs)` |


### Private Methods

| Method Name | Signature |
|-----------|---------|
| `_create_compatible_apps` | `(self, avs)` |
| `_get_field_value_map` | `(self, meta, exclude=None)` |
| `_reset_initial_attrs` | `(self, attrs=None)` |
| `_send_changes` | `(self, old_attr, new_attr_kw)` |


## Custom Managers

### default

**Class:** `VersionManager`

*Base for all managers in AMO.

Returns BaseQuerySets.

If a model has translated fields, they'll be attached through a transform
function.*

#### Custom Methods

##### `approved(self)`


##### `auto_approvable(self)`

*Returns a queryset filtered with just the versions that should
attempted for auto-approval by the cron job.*

##### `latest_public_compatible_with(self, application, appversions, *, strict_compat_mode=False)`

*Return a queryset filtering the versions so that they are public,
listed, and compatible with the application and appversions parameters
passed. The queryset is ordered by creation date descending, allowing
the caller to get the latest compatible version available.

`application` is an application id
`appversions` is a dict containing min and max values, as version ints.

By default, `appversions['max']` is only considered for versions that
have strict compatibility enabled, unless the `strict_compat_mode`
parameter is also True.

Regardless of whether appversions are passed or not, the queryset will
be annotated with min_compatible_version and max_compatible_version
values, corresponding to the min and max application version each
Version is compatible with.*

##### `should_have_due_date(self, negate=False)`

*Returns a queryset filtered to versions that should have a due date set.
If `negate=True` the queryset will contain versions that should not have a
due date instead.*

##### `transform(self, fn)`


##### `valid(self)`


#### Custom QuerySet

**Class:** `BaseQuerySet`

*Represent a lazy database lookup for a set of objects.*

##### Custom Methods

###### `no_transforms(self)`

###### `only_translations(self)`

*Remove all transforms except translations.*

###### `optimized_count(self)`

*Slightly optimized count() for cases where there is a DISTINCT in the
queryset.

When a count() call is made on a queryset that has a distinct, that
causes django to run the full SELECT (including all fields, distinct,
ordering etc) in a subquery and then COUNT() on the result of that
subquery, which is costly/innefficient. That's tracked in
https://code.djangoproject.com/ticket/30685.
We can't easily fix the fact that there is a subquery, but we can
avoid selecting all fields and ordering in that subquery needlessly.*

###### `pop_transforms(self)`

###### `transform(self, fn)`

### objects

**Class:** `VersionManager`

*Base for all managers in AMO.

Returns BaseQuerySets.

If a model has translated fields, they'll be attached through a transform
function.*

#### Custom Methods

##### `approved(self)`


##### `auto_approvable(self)`

*Returns a queryset filtered with just the versions that should
attempted for auto-approval by the cron job.*

##### `latest_public_compatible_with(self, application, appversions, *, strict_compat_mode=False)`

*Return a queryset filtering the versions so that they are public,
listed, and compatible with the application and appversions parameters
passed. The queryset is ordered by creation date descending, allowing
the caller to get the latest compatible version available.

`application` is an application id
`appversions` is a dict containing min and max values, as version ints.

By default, `appversions['max']` is only considered for versions that
have strict compatibility enabled, unless the `strict_compat_mode`
parameter is also True.

Regardless of whether appversions are passed or not, the queryset will
be annotated with min_compatible_version and max_compatible_version
values, corresponding to the min and max application version each
Version is compatible with.*

##### `should_have_due_date(self, negate=False)`

*Returns a queryset filtered to versions that should have a due date set.
If `negate=True` the queryset will contain versions that should not have a
due date instead.*

##### `transform(self, fn)`


##### `valid(self)`


#### Custom QuerySet

**Class:** `BaseQuerySet`

*Represent a lazy database lookup for a set of objects.*

##### Custom Methods

###### `no_transforms(self)`

###### `only_translations(self)`

*Remove all transforms except translations.*

###### `optimized_count(self)`

*Slightly optimized count() for cases where there is a DISTINCT in the
queryset.

When a count() call is made on a queryset that has a distinct, that
causes django to run the full SELECT (including all fields, distinct,
ordering etc) in a subquery and then COUNT() on the result of that
subquery, which is costly/innefficient. That's tracked in
https://code.djangoproject.com/ticket/30685.
We can't easily fix the fact that there is a subquery, but we can
avoid selecting all fields and ordering in that subquery needlessly.*

###### `pop_transforms(self)`

###### `transform(self, fn)`

### unfiltered

**Class:** `VersionManager`

*Base for all managers in AMO.

Returns BaseQuerySets.

If a model has translated fields, they'll be attached through a transform
function.*

#### Custom Methods

##### `approved(self)`


##### `auto_approvable(self)`

*Returns a queryset filtered with just the versions that should
attempted for auto-approval by the cron job.*

##### `latest_public_compatible_with(self, application, appversions, *, strict_compat_mode=False)`

*Return a queryset filtering the versions so that they are public,
listed, and compatible with the application and appversions parameters
passed. The queryset is ordered by creation date descending, allowing
the caller to get the latest compatible version available.

`application` is an application id
`appversions` is a dict containing min and max values, as version ints.

By default, `appversions['max']` is only considered for versions that
have strict compatibility enabled, unless the `strict_compat_mode`
parameter is also True.

Regardless of whether appversions are passed or not, the queryset will
be annotated with min_compatible_version and max_compatible_version
values, corresponding to the min and max application version each
Version is compatible with.*

##### `should_have_due_date(self, negate=False)`

*Returns a queryset filtered to versions that should have a due date set.
If `negate=True` the queryset will contain versions that should not have a
due date instead.*

##### `transform(self, fn)`


##### `valid(self)`


#### Custom QuerySet

**Class:** `BaseQuerySet`

*Represent a lazy database lookup for a set of objects.*

##### Custom Methods

###### `no_transforms(self)`

###### `only_translations(self)`

*Remove all transforms except translations.*

###### `optimized_count(self)`

*Slightly optimized count() for cases where there is a DISTINCT in the
queryset.

When a count() call is made on a queryset that has a distinct, that
causes django to run the full SELECT (including all fields, distinct,
ordering etc) in a subquery and then COUNT() on the result of that
subquery, which is costly/innefficient. That's tracked in
https://code.djangoproject.com/ticket/30685.
We can't easily fix the fact that there is a subquery, but we can
avoid selecting all fields and ordering in that subquery needlessly.*

###### `pop_transforms(self)`

###### `transform(self, fn)`

### unfiltered_for_relations

**Class:** `UnfilteredVersionManagerForRelations`

*Like VersionManager, but defaults to include deleted objects.

Designed to be used in reverse relations of Versions like this:
<Addon>.versions(manager='unfiltered_for_relations').all(), for when you
want to use the related manager but need to include deleted versions.

unfiltered_for_relations = UnfilteredVersionManagerForRelations() is
defined in Version for this to work.*

#### Custom Methods

##### `approved(self)`


##### `auto_approvable(self)`

*Returns a queryset filtered with just the versions that should
attempted for auto-approval by the cron job.*

##### `latest_public_compatible_with(self, application, appversions, *, strict_compat_mode=False)`

*Return a queryset filtering the versions so that they are public,
listed, and compatible with the application and appversions parameters
passed. The queryset is ordered by creation date descending, allowing
the caller to get the latest compatible version available.

`application` is an application id
`appversions` is a dict containing min and max values, as version ints.

By default, `appversions['max']` is only considered for versions that
have strict compatibility enabled, unless the `strict_compat_mode`
parameter is also True.

Regardless of whether appversions are passed or not, the queryset will
be annotated with min_compatible_version and max_compatible_version
values, corresponding to the min and max application version each
Version is compatible with.*

##### `should_have_due_date(self, negate=False)`

*Returns a queryset filtered to versions that should have a due date set.
If `negate=True` the queryset will contain versions that should not have a
due date instead.*

##### `transform(self, fn)`


##### `valid(self)`


#### Custom QuerySet

**Class:** `BaseQuerySet`

*Represent a lazy database lookup for a set of objects.*

##### Custom Methods

###### `no_transforms(self)`

###### `only_translations(self)`

*Remove all transforms except translations.*

###### `optimized_count(self)`

*Slightly optimized count() for cases where there is a DISTINCT in the
queryset.

When a count() call is made on a queryset that has a distinct, that
causes django to run the full SELECT (including all fields, distinct,
ordering etc) in a subquery and then COUNT() on the result of that
subquery, which is costly/innefficient. That's tracked in
https://code.djangoproject.com/ticket/30685.
We can't easily fix the fact that there is a subquery, but we can
avoid selecting all fields and ordering in that subquery needlessly.*

###### `pop_transforms(self)`

###### `transform(self, fn)`


---

!!! THIS DOCUMENT WAS *AUTOGENERATED* ON 2025-08-02 !!!