Skip to content

Commit 496f3c8

Browse files
committed
Adapt __str__ and __repr__ methods for DB
This commit removes some debugging functionability in favor of production DB. `__str__` and `__repr__` methods won't be so descriptive now since we are removing some information from their rendering. This is because to render them properly we need to hit the DB multiple times in the worst case --generating 500 on some user requests that need to be logged in Sentry/New Relic. There are better ways for this: disabling logging on production and enabling it on DEBUG + Django Shell, but that requires more extra work that doesn't seems super priority right now. We can come back later and add them as we need them if we want. Closes #10954
1 parent a6130d3 commit 496f3c8

File tree

19 files changed

+52
-114
lines changed

19 files changed

+52
-114
lines changed

readthedocs/analytics/models.py

-3
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ class Meta:
102102
),
103103
]
104104

105-
def __str__(self):
106-
return f"PageView: [{self.project.slug}] - {self.full_path or self.path} for {self.date}"
107-
108105
@classmethod
109106
def top_viewed_pages(
110107
cls, project, since=None, limit=10, status=200, per_version=False

readthedocs/builds/models.py

+2-29
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from django.db import models
1212
from django.urls import reverse
1313
from django.utils import timezone
14-
from django.utils.translation import gettext
1514
from django.utils.translation import gettext_lazy as _
1615
from django_extensions.db.models import TimeStampedModel
1716
from polymorphic.models import PolymorphicModel
@@ -210,13 +209,7 @@ class Meta:
210209
ordering = ["-verbose_name"]
211210

212211
def __str__(self):
213-
return gettext(
214-
"Version {version} of {project} ({pk})".format(
215-
version=self.verbose_name,
216-
project=self.project,
217-
pk=self.pk,
218-
),
219-
)
212+
return self.verbose_name
220213

221214
@property
222215
def is_private(self):
@@ -940,17 +933,6 @@ def save(self, *args, **kwargs): # noqa
940933
super().save(*args, **kwargs)
941934
self._config_changed = False
942935

943-
def __str__(self):
944-
return gettext(
945-
"Build {project} for {usernames} ({pk})".format(
946-
project=self.project,
947-
usernames=" ".join(
948-
self.project.users.all().values_list("username", flat=True),
949-
),
950-
pk=self.pk,
951-
),
952-
)
953-
954936
def get_absolute_url(self):
955937
return reverse("builds_detail", args=[self.project.slug, self.pk])
956938

@@ -1159,11 +1141,6 @@ class Meta:
11591141

11601142
objects = RelatedBuildQuerySet.as_manager()
11611143

1162-
def __str__(self):
1163-
return gettext("Build command {pk} for build {build}").format(
1164-
pk=self.pk, build=self.build
1165-
)
1166-
11671144
@property
11681145
def run_time(self):
11691146
"""Total command runtime in seconds."""
@@ -1347,11 +1324,7 @@ def get_edit_url(self):
13471324

13481325
def __str__(self):
13491326
class_name = self.__class__.__name__
1350-
return (
1351-
f"({self.priority}) "
1352-
f"{class_name}/{self.get_action_display()} "
1353-
f"for {self.project.slug}:{self.get_version_type_display()}"
1354-
)
1327+
return f"({self.priority}) {class_name}/{self.get_action_display()}"
13551328

13561329

13571330
class RegexAutomationRule(VersionAutomationRule):

readthedocs/builds/querysets.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
EXTERNAL,
1414
)
1515
from readthedocs.core.permissions import AdminPermission
16+
from readthedocs.core.querysets import NoReprQuerySet
1617
from readthedocs.core.utils.extend import SettingsOverrideObject
1718
from readthedocs.projects import constants
1819
from readthedocs.projects.models import Project
@@ -23,7 +24,7 @@
2324
__all__ = ["VersionQuerySet", "BuildQuerySet", "RelatedBuildQuerySet"]
2425

2526

26-
class VersionQuerySetBase(models.QuerySet):
27+
class VersionQuerySetBase(NoReprQuerySet, models.QuerySet):
2728

2829
"""Versions take into account their own privacy_level setting."""
2930

@@ -145,7 +146,7 @@ class VersionQuerySet(SettingsOverrideObject):
145146
_default_class = VersionQuerySetBase
146147

147148

148-
class BuildQuerySet(models.QuerySet):
149+
class BuildQuerySet(NoReprQuerySet, models.QuerySet):
149150

150151
"""
151152
Build objects that are privacy aware.
@@ -269,7 +270,7 @@ def concurrent(self, project):
269270
return (limit_reached, concurrent, max_concurrent)
270271

271272

272-
class RelatedBuildQuerySet(models.QuerySet):
273+
class RelatedBuildQuerySet(NoReprQuerySet, models.QuerySet):
273274

274275
"""
275276
For models with association to a project through :py:class:`Build`.

readthedocs/core/models.py

-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from django.contrib.auth.models import User
55
from django.db import models
66
from django.urls import reverse
7-
from django.utils.translation import gettext
87
from django.utils.translation import gettext_lazy as _
98
from django_extensions.db.models import TimeStampedModel
109
from simple_history import register
@@ -46,9 +45,6 @@ class UserProfile(TimeStampedModel):
4645
# Model history
4746
history = ExtraHistoricalRecords()
4847

49-
def __str__(self):
50-
return gettext("%(username)s's profile") % {"username": self.user.username}
51-
5248
def get_absolute_url(self):
5349
return reverse(
5450
"profiles_profile_detail",

readthedocs/core/querysets.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class NoReprQuerySet:
2+
3+
"""
4+
Basic queryset to override `__repr__` function due to logging issues.
5+
6+
This may be a temporary solution for now and it can be improved to detect
7+
if we are under DEBUG and/or on an interactive shell.
8+
9+
https://github.com/readthedocs/readthedocs.org/issues/10954
10+
https://github.com/readthedocs/readthedocs.org/issues/10954#issuecomment-2057596044
11+
https://github.com/readthedocs/readthedocs.org/issues/10954#issuecomment-2057951300
12+
"""
13+
14+
def __repr__(self):
15+
return self.__class__.__name__

readthedocs/integrations/models.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,7 @@ class Integration(TimeStampedModel):
309309
has_sync = False
310310

311311
def __str__(self):
312-
return _("{0} for {1}").format(
313-
self.get_integration_type_display(), self.project.name
314-
)
312+
return self.get_integration_type_display()
315313

316314
def save(self, *args, **kwargs):
317315
if not self.secret:

readthedocs/invitations/models.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ def invite(self, from_user, obj, to_user=None, to_email=None, request=None):
4545
"""
4646
if not to_user and not to_email:
4747
raise ValueError("A user or email must be provided")
48-
fields = dict(
49-
content_type=ContentType.objects.get_for_model(obj),
50-
object_id=obj.pk,
51-
)
48+
49+
fields = {
50+
"content_type": ContentType.objects.get_for_model(obj),
51+
"object_id": obj.pk,
52+
}
5253
if to_user:
5354
fields["to_user"] = to_user
5455
else:
@@ -241,6 +242,3 @@ def create_audit_log(self, action, request, user=None):
241242
user=user,
242243
**kwargs,
243244
)
244-
245-
def __str__(self):
246-
return f"Invitation for {self.username} to join {self.object}"

readthedocs/notifications/querysets.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from django.utils import timezone
55

66
from readthedocs.core.permissions import AdminPermission
7+
from readthedocs.core.querysets import NoReprQuerySet
78

89
from .constants import CANCELLED, READ, UNREAD
910

1011

11-
class NotificationQuerySet(models.QuerySet):
12+
class NotificationQuerySet(NoReprQuerySet, models.QuerySet):
1213
def add(self, *args, **kwargs):
1314
"""
1415
Create a notification without duplicating it.

readthedocs/oauth/models.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Meta:
6161
db_table = "oauth_remoteorganization_2020"
6262

6363
def __str__(self):
64-
return "Remote organization: {name}".format(name=self.slug)
64+
return self.slug
6565

6666
def get_remote_organization_relation(self, user, social_account):
6767
"""Return RemoteOrganizationRelation object for the remote organization."""
@@ -96,9 +96,6 @@ class Meta:
9696
"account",
9797
)
9898

99-
def __str__(self):
100-
return f"{self.user.username} <-> {self.remote_organization.name}"
101-
10299

103100
class RemoteRepository(TimeStampedModel):
104101

@@ -189,7 +186,7 @@ class Meta:
189186
db_table = "oauth_remoterepository_2020"
190187

191188
def __str__(self):
192-
return "Remote repository: {}".format(self.html_url)
189+
return self.html_url
193190

194191
def matches(self, user):
195192
"""Existing projects connected to this RemoteRepository."""
@@ -250,6 +247,3 @@ class Meta:
250247
"remote_repository",
251248
"account",
252249
)
253-
254-
def __str__(self):
255-
return f"{self.user.username} <-> {self.remote_repository.full_name}"

readthedocs/oauth/querysets.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
from django.db import models
44

5+
from readthedocs.core.querysets import NoReprQuerySet
56

6-
class RelatedUserQuerySet(models.QuerySet):
7+
8+
class RelatedUserQuerySet(NoReprQuerySet, models.QuerySet):
79

810
"""For models with relations through :py:class:`User`."""
911

readthedocs/organizations/models.py

+1-20
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,6 @@ class OrganizationOwner(models.Model):
214214
on_delete=models.CASCADE,
215215
)
216216

217-
def __str__(self):
218-
return _("{org} owner {owner}").format(
219-
org=self.organization.name,
220-
owner=self.owner.username,
221-
)
222-
223217

224218
class Team(models.Model):
225219

@@ -325,10 +319,7 @@ class Meta:
325319
unique_together = ("team", "email")
326320

327321
def __str__(self):
328-
return "{email} to {team}".format(
329-
email=self.email,
330-
team=self.team,
331-
)
322+
return self.email
332323

333324
def save(self, *args, **kwargs):
334325
hash_ = salted_hmac(
@@ -399,16 +390,6 @@ class Meta:
399390

400391
objects = TeamMemberManager()
401392

402-
def __str__(self):
403-
state = ""
404-
if self.is_invite:
405-
state = " (pending)"
406-
return "{username} to {team}{state}".format(
407-
username=self.username,
408-
team=self.team,
409-
state=state,
410-
)
411-
412393
@property
413394
def username(self):
414395
"""Return member username or invite email as username."""

readthedocs/organizations/querysets.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
from django.utils import timezone
99
from djstripe.enums import InvoiceStatus, SubscriptionStatus
1010

11+
from readthedocs.core.querysets import NoReprQuerySet
1112
from readthedocs.core.utils.extend import SettingsOverrideObject
1213
from readthedocs.subscriptions.constants import DISABLE_AFTER_DAYS
1314

1415

15-
class BaseOrganizationQuerySet(models.QuerySet):
16+
class BaseOrganizationQuerySet(NoReprQuerySet, models.QuerySet):
1617

1718
"""Organizations queryset."""
1819

readthedocs/projects/models.py

+3-17
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ class ProjectRelationship(models.Model):
111111

112112
objects = ChildRelatedProjectQuerySet.as_manager()
113113

114-
def __str__(self):
115-
return "{} -> {}".format(self.parent, self.child)
116-
117114
def save(self, *args, **kwargs):
118115
if not self.alias:
119116
self.alias = self.child.slug
@@ -1506,9 +1503,6 @@ def get_absolute_url(self):
15061503
filename=self.path,
15071504
)
15081505

1509-
def __str__(self):
1510-
return "{}: {}".format(self.name, self.project)
1511-
15121506

15131507
class HTMLFile(ImportedFile):
15141508

@@ -1696,9 +1690,6 @@ def sign_payload(self, payload):
16961690
)
16971691
return digest.hexdigest()
16981692

1699-
def __str__(self):
1700-
return f"{self.project.slug} {self.url}"
1701-
17021693

17031694
class Domain(TimeStampedModel):
17041695

@@ -1790,10 +1781,7 @@ class Meta:
17901781
ordering = ("-canonical", "-machine", "domain")
17911782

17921783
def __str__(self):
1793-
return "{domain} pointed at {project}".format(
1794-
domain=self.domain,
1795-
project=self.project.name,
1796-
)
1784+
return self.domain
17971785

17981786
@property
17991787
def is_valid(self):
@@ -1864,7 +1852,7 @@ class HTTPHeader(TimeStampedModel, models.Model):
18641852
)
18651853

18661854
def __str__(self):
1867-
return f"HttpHeader: {self.name} on {self.domain.domain}"
1855+
return self.name
18681856

18691857

18701858
class Feature(models.Model):
@@ -2033,9 +2021,7 @@ def add_features(sender, **kwargs):
20332021
objects = FeatureQuerySet.as_manager()
20342022

20352023
def __str__(self):
2036-
return "{} feature".format(
2037-
self.get_feature_display(),
2038-
)
2024+
return self.get_feature_display()
20392025

20402026
def get_feature_display(self):
20412027
"""

readthedocs/projects/querysets.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
from django.db.models import Count, OuterRef, Prefetch, Q, Subquery
44

55
from readthedocs.core.permissions import AdminPermission
6+
from readthedocs.core.querysets import NoReprQuerySet
67
from readthedocs.core.utils.extend import SettingsOverrideObject
78
from readthedocs.projects import constants
89
from readthedocs.subscriptions.products import get_feature
910

1011

11-
class ProjectQuerySetBase(models.QuerySet):
12+
class ProjectQuerySetBase(NoReprQuerySet, models.QuerySet):
1213

1314
"""Projects take into account their own privacy_level setting."""
1415

@@ -169,7 +170,7 @@ class ProjectQuerySet(SettingsOverrideObject):
169170
_default_class = ProjectQuerySetBase
170171

171172

172-
class RelatedProjectQuerySet(models.QuerySet):
173+
class RelatedProjectQuerySet(NoReprQuerySet, models.QuerySet):
173174

174175
"""
175176
Useful for objects that relate to Project and its permissions.
@@ -220,7 +221,7 @@ class ChildRelatedProjectQuerySet(RelatedProjectQuerySet):
220221
use_for_related_fields = True
221222

222223

223-
class FeatureQuerySet(models.QuerySet):
224+
class FeatureQuerySet(NoReprQuerySet, models.QuerySet):
224225
use_for_related_fields = True
225226

226227
def for_project(self, project):

0 commit comments

Comments
 (0)