mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
Push verbose_name to the model-level
at least for those fields where it is currently used. this necessitates a patch to the migration machinery, which this commit adds See #161
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
from django.db import models
|
||||
|
||||
IGNORED_ATTRS = ['verbose_name', 'help_text']
|
||||
|
||||
original_deconstruct = models.Field.deconstruct
|
||||
|
||||
|
||||
def new_deconstruct(self):
|
||||
# works around the non-fix of https://code.djangoproject.com/ticket/21498 (I don't agree with the reasoning that
|
||||
# "in principle any field could influence the database schema"; you must be _insane_ if verbose_name or help_text
|
||||
# actually do, and the cost of the migrations is real)
|
||||
# solution from https://stackoverflow.com/a/39801321/339144
|
||||
name, path, args, kwargs = original_deconstruct(self)
|
||||
for attr in IGNORED_ATTRS:
|
||||
kwargs.pop(attr, None)
|
||||
return name, path, args, kwargs
|
||||
|
||||
|
||||
def monkey_patch_deconstruct():
|
||||
models.Field.deconstruct = new_deconstruct
|
||||
|
||||
8
bsmain/management/commands/makemigrations.py
Normal file
8
bsmain/management/commands/makemigrations.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.core.management.commands.makemigrations import Command as OriginalCommand
|
||||
|
||||
from . import monkey_patch_deconstruct
|
||||
monkey_patch_deconstruct()
|
||||
|
||||
|
||||
class Command(OriginalCommand):
|
||||
pass # no changes, except the monkey patch above
|
||||
@@ -1,6 +1,9 @@
|
||||
import time
|
||||
from django.core.management.commands.migrate import Command as DjangoMigrateCommand
|
||||
|
||||
from . import monkey_patch_deconstruct
|
||||
monkey_patch_deconstruct() # needed for migrate.py to avoid the warning about non-reflected changes
|
||||
|
||||
|
||||
class Command(DjangoMigrateCommand):
|
||||
# We override the default Django migrate command to add the elapsed time for each migration. (This could in theory
|
||||
@@ -10,8 +13,7 @@ class Command(DjangoMigrateCommand):
|
||||
# We care more about the elapsed time for each migration than the average Django user because sqlite takes such a
|
||||
# prominent role in our architecture, and because migrations are run out of our direct control ("self hosted").
|
||||
#
|
||||
# AFAIU, "just dropping a file called migrate.py in one of our apps" is good enough to be the override (and if it
|
||||
# isn't, it's not critical, since all we do is add a bit more info to the output).
|
||||
# AFAIU, "just dropping a file called migrate.py in one of our apps" is good enough to be the override.
|
||||
|
||||
def migration_progress_callback(self, action, migration=None, fake=False):
|
||||
# Django 4.2's method, with a single change
|
||||
|
||||
@@ -3,7 +3,6 @@ from django.contrib.auth import get_user_model
|
||||
from django.template.defaultfilters import yesno
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import pgettext_lazy
|
||||
from django.utils.html import format_html
|
||||
|
||||
from bugsink.utils import assert_
|
||||
@@ -47,8 +46,6 @@ class MyProjectMembershipForm(forms.ModelForm):
|
||||
super().__init__(*args, **kwargs)
|
||||
assert_(self.instance is not None, "This form is only implemented for editing")
|
||||
|
||||
self.fields['role'].label = _("Role")
|
||||
|
||||
if not edit_role:
|
||||
del self.fields['role']
|
||||
|
||||
@@ -66,7 +63,6 @@ class MyProjectMembershipForm(forms.ModelForm):
|
||||
sea_default = self.instance.user.send_email_alerts
|
||||
|
||||
empty_label = _('Default (%s, as per %s settings)') % (yesno(sea_default).capitalize(), sea_defined_at)
|
||||
self.fields['send_email_alerts'].label = _("Send email alerts")
|
||||
self.fields['send_email_alerts'].empty_label = empty_label
|
||||
self.fields['send_email_alerts'].widget.choices[0] = ("unknown", empty_label)
|
||||
|
||||
@@ -87,10 +83,6 @@ class ProjectForm(forms.ModelForm):
|
||||
team_qs = kwargs.pop("team_qs", None)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields["name"].label = pgettext_lazy("Project", "Name")
|
||||
self.fields["visibility"].label = _("Visibility")
|
||||
|
||||
self.fields["retention_max_event_count"].label = _("Retention max event count")
|
||||
self.fields["retention_max_event_count"].help_text = _("The maximum number of events to store before evicting.")
|
||||
if self.instance is not None and self.instance.pk is not None:
|
||||
# for editing, we disallow changing the team. consideration: it's somewhat hard to see what the consequences
|
||||
|
||||
@@ -3,7 +3,7 @@ import uuid
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
|
||||
from bugsink.app_settings import get_settings
|
||||
from bugsink.transaction import delay_on_commit
|
||||
@@ -76,7 +76,7 @@ class Project(models.Model):
|
||||
|
||||
team = models.ForeignKey("teams.Team", blank=False, null=True, on_delete=models.SET_NULL)
|
||||
|
||||
name = models.CharField(max_length=255, blank=False, null=False, unique=True)
|
||||
name = models.CharField(pgettext_lazy("Project", "Name"), max_length=255, blank=False, null=False, unique=True)
|
||||
slug = models.SlugField(max_length=50, blank=False, null=False, unique=True)
|
||||
is_deleted = models.BooleanField(default=False)
|
||||
|
||||
@@ -109,7 +109,7 @@ class Project(models.Model):
|
||||
|
||||
# visibility
|
||||
visibility = models.IntegerField(
|
||||
choices=ProjectVisibility.choices, default=ProjectVisibility.TEAM_MEMBERS,
|
||||
_("Visibility"), choices=ProjectVisibility.choices, default=ProjectVisibility.TEAM_MEMBERS,
|
||||
help_text=_("Which users can see this project and its issues?"))
|
||||
|
||||
# ingestion/digestion quota
|
||||
@@ -117,7 +117,7 @@ class Project(models.Model):
|
||||
next_quota_check = models.PositiveIntegerField(null=False, default=0)
|
||||
|
||||
# retention
|
||||
retention_max_event_count = models.PositiveIntegerField(default=10_000)
|
||||
retention_max_event_count = models.PositiveIntegerField(_("Retention max event count"), default=10_000)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -179,9 +179,9 @@ class ProjectMembership(models.Model):
|
||||
project = models.ForeignKey(Project, on_delete=models.DO_NOTHING)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
|
||||
send_email_alerts = models.BooleanField(default=None, null=True)
|
||||
send_email_alerts = models.BooleanField(_("Send email alerts"), default=None, null=True)
|
||||
|
||||
role = models.IntegerField(choices=ProjectRole.choices, default=ProjectRole.MEMBER)
|
||||
role = models.IntegerField(_("Role"), choices=ProjectRole.choices, default=ProjectRole.MEMBER)
|
||||
accepted = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -2,7 +2,6 @@ from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.template.defaultfilters import yesno
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import pgettext_lazy
|
||||
|
||||
from bugsink.utils import assert_
|
||||
from .models import TeamRole, TeamMembership, Team
|
||||
@@ -43,8 +42,6 @@ class MyTeamMembershipForm(forms.ModelForm):
|
||||
super().__init__(*args, **kwargs)
|
||||
assert_(self.instance is not None, "This form is only implemented for editing")
|
||||
|
||||
self.fields['role'].label = _("Role")
|
||||
|
||||
if not edit_role:
|
||||
del self.fields['role']
|
||||
|
||||
@@ -52,7 +49,6 @@ class MyTeamMembershipForm(forms.ModelForm):
|
||||
global_send_email_alerts_text = yesno(global_send_email_alerts).capitalize()
|
||||
|
||||
empty_label = _("User-default (%s)") % global_send_email_alerts_text
|
||||
self.fields['send_email_alerts'].label = _("Send email alerts")
|
||||
self.fields['send_email_alerts'].empty_label = empty_label
|
||||
self.fields['send_email_alerts'].widget.choices[0] = ("unknown", empty_label)
|
||||
|
||||
@@ -69,8 +65,3 @@ class TeamForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Team
|
||||
fields = ["name", "visibility"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['name'].label = pgettext_lazy("Team", "Name")
|
||||
self.fields['visibility'].label = _("Visibility")
|
||||
|
||||
@@ -3,7 +3,7 @@ import uuid
|
||||
from django.db import models
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
|
||||
|
||||
class TeamRole(models.IntegerChoices):
|
||||
@@ -27,9 +27,10 @@ class TeamVisibility(models.IntegerChoices):
|
||||
class Team(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
|
||||
name = models.CharField(max_length=255, blank=False, null=False, unique=True)
|
||||
name = models.CharField(pgettext_lazy("Team", "Name"), max_length=255, blank=False, null=False, unique=True)
|
||||
|
||||
visibility = models.IntegerField(
|
||||
_("Visibility"),
|
||||
choices=TeamVisibility.choices, default=TeamVisibility.DISCOVERABLE,
|
||||
help_text=_("Which users can see this team and its issues?"))
|
||||
|
||||
@@ -49,8 +50,8 @@ class TeamMembership(models.Model):
|
||||
team = models.ForeignKey(Team, on_delete=models.CASCADE)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
|
||||
send_email_alerts = models.BooleanField(default=None, null=True, blank=True)
|
||||
role = models.IntegerField(choices=TeamRole.choices, default=TeamRole.MEMBER)
|
||||
send_email_alerts = models.BooleanField(_("Send email alerts"), default=None, null=True, blank=True)
|
||||
role = models.IntegerField(_("Role"), choices=TeamRole.choices, default=TeamRole.MEMBER)
|
||||
accepted = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
Reference in New Issue
Block a user