reverse manytomany field between access restrictions and their groups

This commit is contained in:
Laura Klünder 2024-12-11 14:43:27 +01:00
parent 34199b2bf3
commit 450c9486c0
3 changed files with 55 additions and 10 deletions

View file

@ -10,6 +10,7 @@ from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Prefetch, Q from django.db.models import Prefetch, Q
from django.db.models.fields.reverse_related import ManyToManyRel
from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField, from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField,
ModelForm, MultipleChoiceField, Select, ValidationError) ModelForm, MultipleChoiceField, Select, ValidationError)
from django.forms.widgets import HiddenInput, TextInput from django.forms.widgets import HiddenInput, TextInput
@ -171,9 +172,9 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
self.fields.move_to_end('copy_from', last=False) self.fields.move_to_end('copy_from', last=False)
self.fields.move_to_end('name', last=False) self.fields.move_to_end('name', last=False)
if self._meta.model.__name__ == 'AccessRestriction': if self._meta.model.__name__ == 'AccessRestrictionGroup':
self.fields['groups'].label_from_instance = lambda obj: obj.title self.fields['members'].label_from_instance = lambda obj: obj.title
self.fields['groups'].queryset = AccessRestrictionGroup.qs_for_request(self.request) self.fields['members'].queryset = AccessRestriction.qs_for_request(self.request)
elif 'groups' in self.fields: elif 'groups' in self.fields:
kwargs = {'allow_'+self._meta.model._meta.default_related_name: True} kwargs = {'allow_'+self._meta.model._meta.default_related_name: True}
@ -407,7 +408,7 @@ def create_editor_form(editor_model):
'extra_seconds', 'speed', 'can_report_missing', "can_report_mistake", 'extra_seconds', 'speed', 'can_report_missing', "can_report_mistake",
'description', 'speed_up', 'description_up', 'description', 'speed_up', 'description_up',
'report_help_text', 'enter_description', 'level_change_description', 'base_mapdata_accessible', 'report_help_text', 'enter_description', 'level_change_description', 'base_mapdata_accessible',
'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', 'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', 'members',
'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'allow_dynamic_locations', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'allow_dynamic_locations',
'left', 'top', 'right', 'bottom', 'import_tag', 'import_block_data', 'import_block_geom', 'left', 'top', 'right', 'bottom', 'import_tag', 'import_block_data', 'import_block_geom',
'public', 'default', 'dark', 'high_contrast', 'funky', 'randomize_primary_color', 'color_logo', 'public', 'default', 'dark', 'high_contrast', 'funky', 'randomize_primary_color', 'color_logo',
@ -422,7 +423,8 @@ def create_editor_form(editor_model):
'stroke_color', 'stroke_width', 'fill_color', 'interactive', 'point_icon', 'extra_data', 'stroke_color', 'stroke_width', 'fill_color', 'interactive', 'point_icon', 'extra_data',
'show_label', 'show_geometry', 'external_url', 'show_label', 'show_geometry', 'external_url',
] ]
field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many] field_names = [field.name for field in editor_model._meta.get_fields()
if not field.one_to_many and not isinstance(field, ManyToManyRel)]
existing_fields = [name for name in possible_fields if name in field_names] existing_fields = [name for name in possible_fields if name in field_names]
class EditorForm(EditorFormBase, ModelForm): class EditorForm(EditorFormBase, ModelForm):

View file

@ -0,0 +1,41 @@
# Generated by Django 5.0.8 on 2024-12-11 13:24
from django.db import migrations, models
def forwards_func(apps, schema_editor):
AccessRestrictionGroup = apps.get_model('mapdata', 'AccessRestrictionGroup')
for group in AccessRestrictionGroup.objects.prefetch_related("accessrestrictions").all():
group.members.set(group.accessrestrictions.all())
def backwards_func(apps, schema_editor):
AccessRestrictionGroup = apps.get_model('mapdata', 'AccessRestrictionGroup')
for group in AccessRestrictionGroup.objects.prefetch_related("members").all():
group.accessrestrictions.set(group.members.all())
class Migration(migrations.Migration):
dependencies = [
('mapdata', '0113_locationgroup_can_report_mistake'),
]
operations = [
migrations.AddField(
model_name='accessrestrictiongroup',
name='members',
field=models.ManyToManyField(blank=True, to='mapdata.accessrestriction', verbose_name='Access Restrictions'),
),
migrations.RunPython(forwards_func, backwards_func),
migrations.RemoveField(
model_name='accessrestriction',
name='groups',
),
migrations.AlterField(
model_name='accessrestrictiongroup',
name='members',
field=models.ManyToManyField(blank=True, related_name='groups', to='mapdata.accessrestriction',
verbose_name='Access Restrictions'),
),
]

View file

@ -21,7 +21,6 @@ class AccessRestriction(TitledMixin, models.Model):
An access restriction An access restriction
""" """
public = models.BooleanField(default=False, verbose_name=_('public')) public = models.BooleanField(default=False, verbose_name=_('public'))
groups = models.ManyToManyField('mapdata.AccessRestrictionGroup', verbose_name=_('Groups'), blank=True)
class Meta: class Meta:
verbose_name = _('Access Restriction') verbose_name = _('Access Restriction')
@ -60,6 +59,9 @@ class AccessRestrictionGroup(TitledMixin, models.Model):
""" """
An access restriction group An access restriction group
""" """
members = models.ManyToManyField('mapdata.AccessRestriction', verbose_name=_('Access Restrictions'), blank=True,
related_name="groups")
class Meta: class Meta:
verbose_name = _('Access Restriction Group') verbose_name = _('Access Restriction Group')
verbose_name_plural = _('Access Restriction Groups') verbose_name_plural = _('Access Restriction Groups')
@ -77,7 +79,7 @@ class AccessRestrictionGroup(TitledMixin, models.Model):
permissions = AccessPermission.get_for_request(request) permissions = AccessPermission.get_for_request(request)
# now we filter out groups where the user doesn't have a permission for all members # now we filter out groups where the user doesn't have a permission for all members
filter_perms = all_permissions - permissions filter_perms = all_permissions - permissions
return ~Q(accessrestrictions__pk__in=filter_perms) return ~Q(members__pk__in=filter_perms)
@classmethod @classmethod
def qs_for_user(cls, user): def qs_for_user(cls, user):
@ -91,7 +93,7 @@ class AccessRestrictionGroup(TitledMixin, models.Model):
permissions = AccessPermission.get_for_user(user) permissions = AccessPermission.get_for_user(user)
# now we filter out groups where the user doesn't have a permission for all members # now we filter out groups where the user doesn't have a permission for all members
filter_perms = all_permissions - permissions filter_perms = all_permissions - permissions
return ~Q(accessrestrictions__pk__in=filter_perms) return ~Q(members__pk__in=filter_perms)
def default_valid_until(): def default_valid_until():
@ -288,7 +290,7 @@ class AccessPermission(models.Model):
result = tuple( result = tuple(
qs.select_related( qs.select_related(
'access_restriction_group' 'access_restriction_group'
).prefetch_related('access_restriction_group__accessrestrictions') ).prefetch_related('access_restriction_group__members')
) )
# collect permissions (can be multiple for one restriction) # collect permissions (can be multiple for one restriction)
@ -297,7 +299,7 @@ class AccessPermission(models.Model):
if permission.access_restriction_id: if permission.access_restriction_id:
permissions.setdefault(permission.access_restriction_id, set()).add(permission.expire_date) permissions.setdefault(permission.access_restriction_id, set()).add(permission.expire_date)
if permission.access_restriction_group_id: if permission.access_restriction_group_id:
for member in permission.access_restriction_group.accessrestrictions.all(): for member in permission.access_restriction_group.members.all():
permissions.setdefault(member.pk, set()).add(permission.expire_date) permissions.setdefault(member.pk, set()).add(permission.expire_date)
# get latest expire date for each permission # get latest expire date for each permission