class RoleSerializer(serializers.ModelSerializer): """Role Serializer""" permissions = serializers.MultipleChoiceField(choices=PERMISSION_CHOICES) body_detail = BodySerializerMin(read_only=True, source='body') users_detail = UserProfileSerializer(many=True, read_only=True, source='users') bodies = serializers.SerializerMethodField() class Meta: model = BodyRole fields = ('id', 'name', 'inheritable', 'body', 'body_detail', 'bodies', 'permissions', 'users', 'users_detail', 'priority', 'official_post') @classmethod def get_bodies(cls, obj): """Gets bodies including children if inheritable.""" if not obj.inheritable: return BodySerializerMin([obj.body], many=True).data return BodySerializerMin(cls.get_children_recursive(obj.body, []), many=True).data @classmethod def get_children_recursive(cls, body, children): """Returns an array including a body and its children.""" for child_body_relation in body.children.all(): cls.get_children_recursive(child_body_relation.child, children) if body not in children: children.append(body) return children
class AchievementUserSerializer(serializers.ModelSerializer): """Serializer for Achievement model.""" body_detail = BodySerializerMin(read_only=True, source="body") event_detail = EventMinSerializer(read_only=True, source="event") user = UserProfileSerializer(read_only=True) class Meta: model = Achievement fields = ('id', 'title', 'description', 'admin_note', 'body_detail', 'dismissed', 'verified', 'user', 'body', 'verified_by', 'event', 'event_detail', 'offer') @staticmethod def setup_eager_loading(queryset): """Perform necessary eager loading of data.""" queryset = queryset.prefetch_related('body', 'user') return queryset def create(self, validated_data): validated_data['user'] = self.context['request'].user.profile validated_data['dismissed'] = False validated_data['verified'] = False return super().create(validated_data) def update(self, instance, validated_data): validated_data['verified_by'] = self.context['request'].user.profile return super().update(instance, validated_data)
class EventSerializer(serializers.ModelSerializer): """Serializer for Event. This serializer returns only the count of followers in each category, i.e. interested and going and minimal venue info. Use `EventFullSerializer` if you want information on individual users and venues. """ from locations.serializers import LocationSerializerMin from bodies.serializer_min import BodySerializerMin interested_count = serializers.SerializerMethodField() get_interested_count = lambda self, obj: FollowersMethods.get_count(obj, 1) going_count = serializers.SerializerMethodField() get_going_count = lambda self, obj: FollowersMethods.get_count(obj, 2) venues = LocationSerializerMin(many=True, read_only=True) bodies = BodySerializerMin(many=True, read_only=True) class Meta: model = Event fields = ('id', 'str_id', 'name', 'description', 'image_url', 'start_time', 'end_time', 'all_day', 'venues', 'bodies', 'interested_count', 'going_count', 'website_url', 'weight')
class EventFullSerializer(serializers.ModelSerializer): """Serializer for Event with more information. Returns a nested list of followers of each status and detailed information on venues. """ from bodies.serializer_min import BodySerializerMin from locations.serializers import LocationSerializer from locations.models import Location from bodies.models import Body interested_count = serializers.SerializerMethodField() get_interested_count = lambda self, obj: FollowersMethods.get_count(obj, 1) going_count = serializers.SerializerMethodField() get_going_count = lambda self, obj: FollowersMethods.get_count(obj, 2) interested = serializers.SerializerMethodField() get_interested = lambda self, obj: FollowersMethods.get_followers(obj, 1) going = serializers.SerializerMethodField() get_going = lambda self, obj: FollowersMethods.get_followers(obj, 2) venues = LocationSerializer(many=True, read_only=True) venue_names = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name', source='venues') venue_ids = serializers.PrimaryKeyRelatedField( many=True, read_only=False, source='venues', queryset=Location.objects.all(), required=False) bodies = BodySerializerMin(many=True, read_only=True) bodies_id = serializers.PrimaryKeyRelatedField(many=True, read_only=False, queryset=Body.objects.all(), source='bodies') class Meta: model = Event fields = ('id', 'str_id', 'name', 'description', 'image_url', 'start_time', 'end_time', 'all_day', 'venues', 'venue_names', 'bodies', 'bodies_id', 'interested_count', 'going_count', 'interested', 'going', 'venue_ids', 'website_url') def to_representation(self, instance): result = super().to_representation(instance) # Remove unnecessary fields result.pop('venue_ids') return result def create(self, validated_data): result = super().create(validated_data) result.created_by = self.context['request'].user.profile result.save() return result
def search(request): """EXPENSIVE: Search with query param `query` throughout the database.""" MIN_LENGTH = 3 req_query = request.GET.get("query") if not req_query or len(req_query) < MIN_LENGTH: return Response({"message": "No query or too short!"}, status=400) # Search bodies by name and description bodies = query_search(request, MIN_LENGTH, Body.objects, ['name', 'description']) # Search events by name and description events = get_prioritized( query_search(request, MIN_LENGTH, Event.objects, ['name', 'description'])[:20], request) # Search users by only name: don't add anything else here users = query_search(request, MIN_LENGTH, UserProfile.objects, ['name', 'ldap_id', 'roll_no'])[:20] return Response({ "bodies": BodySerializerMin(bodies, many=True).data, "events": EventSerializer(events, many=True).data, "users": UserProfileSerializer(users, many=True).data })
class EventSerializer(serializers.ModelSerializer): """Serializer for Event. This serializer returns only the count of followers in each category, i.e. interested and going and minimal venue info. Use `EventFullSerializer` if you want information on individual users and venues. """ from locations.serializers import LocationSerializerMin from bodies.serializer_min import BodySerializerMin interested_count = serializers.IntegerField(read_only=True) going_count = serializers.IntegerField(read_only=True) user_ues = serializers.SerializerMethodField() get_user_ues = get_user_ues venues = LocationSerializerMin(many=True, read_only=True) bodies = BodySerializerMin(many=True, read_only=True) class Meta: model = Event fields = ('id', 'str_id', 'name', 'description', 'image_url', 'start_time', 'end_time', 'all_day', 'venues', 'bodies', 'interested_count', 'going_count', 'website_url', 'weight', 'user_ues') @staticmethod def setup_eager_loading(queryset, request, extra_prefetch=None): """Perform necessary eager loading of data.""" # Get the fields to be prefetched fields = ['bodies', 'venues', 'user_tags'] # Add prefetch for user_ues if request.user.is_authenticated and hasattr(request.user, 'profile'): user_query = UserEventStatus.objects.filter( user_id=request.user.profile.id) fields.append(Prefetch('ues', queryset=user_query, to_attr='uues')) # Add extra prefetch fields if extra_prefetch: fields += extra_prefetch queryset = queryset.prefetch_related(*fields) # Prefetch counts interested_count = Count('followers', distinct=True, filter=Q(ues__status=1)) going_count = Count('followers', distinct=True, filter=Q(ues__status=2)) queryset = queryset.annotate( interested_count=interested_count).annotate( going_count=going_count) return queryset
class RoleSerializerMinAlt(serializers.ModelSerializer): """Alternative min serializer for BodyRole""" body_detail = BodySerializerMin(read_only=True, source='body') class Meta: model = BodyRole fields = ('id', 'name', 'body_detail', 'priority')
def list(request): queryset = Body.objects.all() queryset = sort_by_field(queryset, 'followers', reverse=True, filt=Q(followers__active=True)) serializer = BodySerializerMin(queryset, many=True) return Response(serializer.data)
def get_children(obj): """Gets a min serialized children of a Body.""" children = obj.children.prefetch_related('child') children = sort_by_field(children, 'child__followers', reverse=True, filt=Q(child__followers__active=True)) return [BodySerializerMin(x.child).data for x in children.all()]
def get_parents(obj): """Gets a min serialized parents of a Body.""" parents = obj.parents.prefetch_related('parent') parents = sort_by_field(parents, 'parent__followers', reverse=True, filt=Q(parent__followers__active=True)) return [BodySerializerMin(x.parent).data for x in parents.all()]
class UserProfileFullSerializer(serializers.ModelSerializer): """Full serializer for UserProfile with detailed information and events.""" from bodies.serializer_min import BodySerializerMin from bodies.models import Body email = serializers.SerializerMethodField() events_interested = serializers.SerializerMethodField() get_events_interested = lambda self, obj: self.get_events(obj, 1) events_going = serializers.SerializerMethodField() get_events_going = lambda self, obj: self.get_events(obj, 2) followed_bodies = BodySerializerMin(many=True, read_only=True) followed_bodies_id = serializers.PrimaryKeyRelatedField( many=True, read_only=False, queryset=Body.objects.all(), source='followed_bodies') roles = RoleSerializer(many=True, read_only=True) former_roles = RoleSerializerMinAlt(many=True, read_only=True) institute_roles = InstituteRoleSerializer(many=True, read_only=True) class Meta: model = UserProfile fields = ('id', 'name', 'profile_pic', 'events_interested', 'events_going', 'email', 'roll_no', 'contact_no', 'about', 'followed_bodies', 'followed_bodies_id', 'roles', 'institute_roles', 'website_url', 'ldap_id', 'hostel', 'former_roles') def get_email(self, obj): """Gets the email only if a user is logged in.""" if self.context['request'].user.is_authenticated: return obj.email return 'N/A' def get_events(self, obj, status): """Returns serialized events for given status.""" from events.serializers import EventSerializer request = self.context['request'] return EventSerializer(get_r_fresh_prioritized_events( obj.followed_events.filter(ues__status=status), request), many=True).data @staticmethod def setup_eager_loading(queryset): """Perform necessary eager loading of data.""" queryset = queryset.prefetch_related('followed_bodies', 'roles', 'roles__body', 'roles__body__children', 'roles__users', 'former_roles', 'former_roles__body') return queryset
class FormerRoleSerializer(serializers.ModelSerializer): """Serializer for UserFormerRole""" id = serializers.ReadOnlyField(read_only=True, source='role.id') name = serializers.ReadOnlyField(read_only=True, source='role.name') body_detail = BodySerializerMin(read_only=True, source='role.body') priority = serializers.ReadOnlyField(read_only=True, source='role.priority') class Meta: model = UserFormerRole fields = ('id', 'name', 'body_detail', 'priority', 'year')
class EventSerializer(serializers.ModelSerializer): """Serializer for Event. This serializer returns only the count of followers in each category, i.e. interested and going and minimal venue info. Use `EventFullSerializer` if you want information on individual users and venues. """ from locations.serializers import LocationSerializerMin from bodies.serializer_min import BodySerializerMin interested_count = serializers.IntegerField(read_only=True) going_count = serializers.IntegerField(read_only=True) user_ues = serializers.SerializerMethodField() get_user_ues = FollowersMethods.get_user_ues venues = LocationSerializerMin(many=True, read_only=True) bodies = BodySerializerMin(many=True, read_only=True) class Meta: model = Event fields = ('id', 'str_id', 'name', 'description', 'image_url', 'start_time', 'end_time', 'all_day', 'venues', 'bodies', 'interested_count', 'going_count', 'website_url', 'weight', 'user_ues') @staticmethod def setup_eager_loading(queryset): """Perform necessary eager loading of data. To be used for EventFullSerializer as well.""" queryset = queryset.prefetch_related('bodies', 'venues', 'ues', 'ues__user', 'user_tags') # Prefetch counts interested_count = Count('followers', distinct=True, filter=Q(ues__status=1)) going_count = Count('followers', distinct=True, filter=Q(ues__status=2)) queryset = queryset.annotate( interested_count=interested_count).annotate( going_count=going_count) return queryset
class AchievementSerializer(serializers.ModelSerializer): """Serializer for Achievement model.""" body_detail = BodySerializerMin(read_only=True, source="body") event_detail = EventMinSerializer(read_only=True, source="event") class Meta: model = Achievement fields = ('id', 'title', 'description', 'body_detail', 'dismissed', 'verified', 'hidden', 'event_detail') @staticmethod def setup_eager_loading(queryset): """Perform necessary eager loading of data.""" queryset = queryset.prefetch_related('body') return queryset
class RoleSerializerWithEvents(serializers.ModelSerializer): """Role Serializer with nested events of bodies""" permissions = serializers.MultipleChoiceField(choices=PERMISSION_CHOICES) events = serializers.SerializerMethodField() body_detail = BodySerializerMin(read_only=True, source='body') bodies = serializers.SerializerMethodField() get_bodies = lambda self, obj: RoleSerializer.get_bodies(obj) class Meta: model = BodyRole fields = ('id', 'name', 'inheritable', 'body', 'body_detail', 'bodies', 'permissions', 'events', 'priority') def get_events(self, obj): return EventSerializer(get_fresh_prioritized_events( obj.body.events.all(), self.context['request'], delta=30), many=True).data
def search(request): """EXPENSIVE: Search with query param `query` throughout the database.""" MIN_LENGTH = 3 req_query = request.GET.get("query") if not req_query or len(req_query) < MIN_LENGTH: return Response({"message": "No query or too short!"}, status=400) types = ('bodies', 'events', 'users') req_types = request.GET.get('types') if req_types: types = tuple(req_types.split(',')) # Include only the types we want bodies, events, users = ([] for i in range(3)) # Search bodies by name and description if 'bodies' in types: bodies = query_search(request, MIN_LENGTH, Body.objects, ['name', 'description'], 'bodies', order_relevance=True) # Search events by name and description if 'events' in types: events = get_prioritized( query_search(request, MIN_LENGTH, Event.objects, ['name', 'description'], 'events')[:20], request) # Search users by only name: don't add anything else here if 'users' in types: users = query_search(request, MIN_LENGTH, UserProfile.objects.filter(active=True), ['name', 'ldap_id', 'roll_no'], 'profiles', order_relevance=True)[:20] return Response({ "bodies": BodySerializerMin(bodies, many=True).data, "events": EventSerializer(events, many=True).data, "users": UserProfileSerializer(users, many=True).data })
def search(request): """EXPENSIVE: Search with query param `query` throughout the database.""" req_query = request.GET.get("query") if not req_query or len(req_query) < 3: return Response({"message": "No query or too short!"}, status=400) # Search bodies by name and description bodies = Body.objects.filter( Q(name__icontains=req_query) | Q(description__icontains=req_query)) # Search events by name and description events = Event.objects.filter( Q(name__icontains=req_query) | Q(description__icontains=req_query)) # Search users by only name: don't add anything else here users = UserProfile.objects.filter(Q(name__icontains=req_query)) return Response({ "bodies": BodySerializerMin(bodies, many=True).data, "events": EventSerializer(events, many=True).data, "users": UserProfileSerializer(users, many=True).data })
def list(cls, request): #pylint: disable=unused-argument queryset = Body.objects.all() serializer = BodySerializerMin(queryset, many=True) return Response(serializer.data)
class EventFullSerializer(serializers.ModelSerializer): """Serializer for Event with more information. Returns a nested list of followers of each status and detailed information on venues. """ from bodies.serializer_min import BodySerializerMin from locations.serializers import LocationSerializerMin from locations.models import Location from bodies.models import Body interested_count = serializers.IntegerField(read_only=True) going_count = serializers.IntegerField(read_only=True) interested = serializers.SerializerMethodField() get_interested = lambda self, obj: get_followers(obj, 1) going = serializers.SerializerMethodField() get_going = lambda self, obj: get_followers(obj, 2) user_ues = serializers.SerializerMethodField() get_user_ues = get_user_ues venues = LocationSerializerMin(many=True, read_only=True) venue_names = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name', source='venues') venue_ids = serializers.PrimaryKeyRelatedField( many=True, read_only=False, source='venues', queryset=Location.objects.all(), required=False) bodies = BodySerializerMin(many=True, read_only=True) bodies_id = serializers.PrimaryKeyRelatedField(many=True, read_only=False, queryset=Body.objects.all(), source='bodies') user_tags = serializers.PrimaryKeyRelatedField( many=True, read_only=False, queryset=UserTag.objects.all(), default=[]) class Meta: model = Event fields = ('id', 'str_id', 'name', 'description', 'image_url', 'start_time', 'end_time', 'all_day', 'venues', 'venue_names', 'bodies', 'bodies_id', 'interested_count', 'going_count', 'interested', 'going', 'venue_ids', 'website_url', 'user_ues', 'notify', 'user_tags') @staticmethod def setup_eager_loading(queryset, request): """Calls the method in EventSerializer adding ues__user""" return EventSerializer.setup_eager_loading( queryset, request, extra_prefetch=['ues', 'ues__user']) def to_representation(self, instance): result = super().to_representation(instance) # Remove unnecessary fields result.pop('venue_ids') return result def create(self, validated_data): validated_data['created_by'] = self.context['request'].user.profile return super().create(validated_data)
def get_children(obj): """Gets a min serialized children of a Body.""" children = sort_by_field(obj.children.all(), 'child__followers', reverse=True) return [BodySerializerMin(x.child).data for x in children]
class UserProfileFullSerializer(serializers.ModelSerializer): """Full serializer for UserProfile with detailed information and events.""" from bodies.serializer_min import BodySerializerMin from bodies.models import Body email = serializers.SerializerMethodField() contact_no = serializers.SerializerMethodField() events_interested = serializers.SerializerMethodField() get_events_interested = lambda self, obj: self.get_events(obj, 1) events_going = serializers.SerializerMethodField() get_events_going = lambda self, obj: self.get_events(obj, 2) followed_bodies = BodySerializerMin(many=True, read_only=True) roles = RoleSerializer(many=True, read_only=True) former_roles = RoleSerializerMinAlt(many=True, read_only=True) institute_roles = InstituteRoleSerializer(many=True, read_only=True) class Meta: model = UserProfile fields = ('id', 'name', 'profile_pic', 'events_interested', 'events_going', 'email', 'roll_no', 'contact_no', 'about', 'followed_bodies', 'fcm_id', 'android_version', 'roles', 'institute_roles', 'website_url', 'ldap_id', 'hostel', 'former_roles') def get_email(self, obj): """Gets the email only if a user is logged in.""" if self.context['request'].user.is_authenticated: return obj.email return 'N/A' def get_contact_no(self, obj): """Gets contact no only if a user is logged in.""" if self.context['request'].user.is_authenticated: return obj.contact_no return 'N/A' def get_events(self, obj, status): """Returns serialized events for given status.""" from events.serializers import EventSerializer request = self.context['request'] return EventSerializer(get_fresh_prioritized_events( obj.followed_events.filter(ues__status=status), request, delta=60), many=True).data @staticmethod def setup_eager_loading(queryset): """Perform necessary eager loading of data.""" queryset = queryset.prefetch_related('followed_bodies', 'roles', 'roles__body', 'roles__body__children', 'roles__users', 'former_roles', 'former_roles__body') return queryset def to_representation(self, instance): result = super().to_representation(instance) result.pop('fcm_id') result.pop('android_version') return settings.USER_PROFILE_FULL_SERIALIZER_TRANSFORM(result)
def get_parents(obj): """Gets a min serialized parents of a Body.""" parents = sort_by_field(obj.parents.all(), 'parent__followers', reverse=True) return [BodySerializerMin(x.parent).data for x in parents]
def get_bodies(cls, obj): """Gets bodies including children if inheritable.""" if not obj.inheritable: return BodySerializerMin([obj.body], many=True).data return BodySerializerMin(cls.get_children_recursive(obj.body, []), many=True).data
def list(cls, request): #pylint: disable=unused-argument queryset = Body.objects.all() queryset = sort_by_field(queryset, 'followers', reverse=True) serializer = BodySerializerMin(queryset, many=True) return Response(serializer.data)