Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speaker relationships #428

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion roundware/api2/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,14 @@ class Meta:
class SpeakerFilterSet(django_filters.FilterSet):
activeyn = django_filters.TypedChoiceFilter(choices=BOOLEAN_CHOICES, coerce=strtobool)
project_id = django_filters.NumberFilter()
parent_ids_or = IntegerListFilter(field_name='parents', lookup_expr='in') # performs OR filtering
parent_ids = IntegerListAndFilter(field_name='parents__id') # performs AND filtering
children_ids_or = IntegerListFilter(field_name='children', lookup_expr='in') # performs OR filtering
hburgund marked this conversation as resolved.
Show resolved Hide resolved
children_ids = IntegerListAndFilter(field_name='children__id') # performs AND filtering

class Meta:
model = Speaker
fields = ["activeyn", "project_id"]
fields = ["activeyn", "project_id", "parents", "children"]


class TagFilterSet(django_filters.FilterSet):
Expand Down
6 changes: 6 additions & 0 deletions roundware/api2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,16 @@ def to_representation(self, obj):


class SpeakerSerializer(serializers.ModelSerializer):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth adding a test of this in the api tests somewhere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean write tests that validate that the serializer is outputting everything in the expected way via the API? I don't think I have an example of this to crib from, but good idea for sure...

children = serializers.SerializerMethodField()

class Meta:
model = Speaker
fields = "__all__"

def get_children(self, obj):
# Access the reverse relationship via `children`
return [child.id for child in obj.children.all()] # Return IDs of children
hburgund marked this conversation as resolved.
Show resolved Hide resolved

def to_representation(self, obj):
result = super(SpeakerSerializer, self).to_representation(obj)
result["project_id"] = result["project"]
Expand Down
4 changes: 2 additions & 2 deletions roundware/api2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,8 +1215,8 @@ class SpeakerViewSet(viewsets.ViewSet):
API V2: api/2/speakers/
api/2/speakers/:id/
"""
queryset = Speaker.objects.all()
permission_classes = (IsAuthenticated,)
queryset = Speaker.objects.prefetch_related('children', 'parents')
permission_classes = (IsAuthenticated, )

def get_object(self, pk):
try:
Expand Down
3 changes: 2 additions & 1 deletion roundware/rw/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,15 @@ class SpeakerAdmin(LeafletGeoAdmin, ProjectProtectedModelAdmin):
list_display = ('id', 'activeyn', 'code', 'project', 'maxvolume', 'minvolume', 'shape', 'uri')
list_filter = ('project', 'activeyn')
list_editable = ('activeyn', 'maxvolume', 'minvolume', 'shape')
filter_horizontal = ('parents', )
ordering = ['id']
save_as = True
save_on_top = True
map_width = "400px"

fieldsets = (
(None, {
'fields': ('activeyn', 'code', 'project', 'maxvolume', 'minvolume', 'uri', )
'fields': ('activeyn', 'code', 'project', 'maxvolume', 'minvolume', 'uri', 'parents' )
}),
('Geographical Data', {
'fields': ('shape', 'attenuation_distance'),
Expand Down
18 changes: 18 additions & 0 deletions roundware/rw/migrations/0040_speaker_parents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.0 on 2024-11-16 12:30

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('rw', '0039_uiitem_filter_remove_validation'),
]

operations = [
migrations.AddField(
model_name='speaker',
name='parents',
field=models.ManyToManyField(blank=True, related_name='children', to='rw.Speaker'),
),
]
2 changes: 2 additions & 0 deletions roundware/rw/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,8 @@ def __init__(self, *args, **kwargs):
attenuation_distance = models.IntegerField()
attenuation_border = models.GeometryField(geography=True, null=True, editable=False)

parents = models.ManyToManyField('Speaker', related_name='children', symmetrical=False, blank=True)

objects = GeoManager()

def __str__(self):
Expand Down
16 changes: 16 additions & 0 deletions roundware/rw/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,19 @@ def test_get_flags(self):

def test_distance(self):
distance = self.asset1.distance({'latitude': 0, 'longitude': 0})

class TestSpeaker(RWTestCase):

def setUp(self):
super().setUp()

self.project = baker.make('rw.Project')
self.speaker1 = baker.make('rw.Speaker', project=self.project)
self.speaker2 = baker.make('rw.Speaker', project=self.project, parents=[self.speaker1])

def test_speaker_children(self):
self.assertEqual(self.speaker1.parents.count(), 0)
self.assertEqual(self.speaker2.parents.count(), 1)
self.assertEqual(self.speaker1.children.count(), 1)
self.assertEqual(self.speaker2.children.count(), 0)

Loading