Source code for matching.serializers

# update these when the User model fields change or if you want to add/remove fields from API responses

#: Maps :class:`~users.models.User` boolean background fields to the label
#: returned in API responses under ``specialCategories``.
#: Add, remove, or rename entries here to control which flags are exposed
#: and how they are labelled without touching serializer logic.
SPECIAL_CATEGORY_FIELDS = {
    'international': 'international',
    'commuter': 'commuter',
    'firstgen': 'firstgen',
    'outofstate': 'outofstate',
    'transfer': 'transfer',
}

#: Maximum number of mentees a single mentor may be assigned.
#: Mirrors :data:`users.models.MAX_MENTEES` and is re-exported here so that
#: matching serializers and services can import from a single location.
MAX_MENTEES = 2


[docs] def serialize_mentor(mentor, score=None): """ Serialize a mentor ``User`` instance into an API-ready dictionary. Includes profile fields, available roster capacity, and an optional compatibility ``score``. The ``score`` field is included in the output only when explicitly supplied, keeping the schema consistent between match-listing responses (which need a score) and plain profile lookups (which do not). :param mentor: The mentor user instance to serialize. :type mentor: users.models.User :param score: Compatibility score for this mentor relative to a specific mentee. Pass ``None`` (default) to omit the field from the response. :type score: float or None :returns: Dictionary of serialized mentor data. When ``score`` is provided the dict includes a ``'score'`` key; otherwise it is absent. :rtype: dict Example — match listing (with score):: >>> serialize_mentor(mentor_user, score=0.87) { 'email': 'mentor@ucla.edu', 'name': 'John Smith', 'score': 0.87, 'available_slots': 1, ... } Example — profile lookup (without score):: >>> serialize_mentor(mentor_user) { 'email': 'mentor@ucla.edu', 'name': 'John Smith', 'available_slots': 2, ... } """ data = { 'email': mentor.email, 'name': full_name(mentor), 'major': mentor.major, 'minor': mentor.minor, 'year': mentor.year, 'hobbies': mentor.hobbies, 'clubs': mentor.clubs, 'goals': mentor.goals, 'specialCategories': special_categories(mentor), 'available_slots': MAX_MENTEES - len(mentor.current_mentees), 'date_joined': mentor.date_joined.isoformat(), } if score is not None: data['score'] = score return data
[docs] def serialize_mentee(mentee): """ Serialize a mentee ``User`` instance into an API-ready dictionary. Returns core profile fields and background category labels. Does not include matching metadata such as ``isMatched`` or ``matchedMentorEmail`` — those are considered internal state and are not exposed through this serializer. :param mentee: The mentee user instance to serialize. :type mentee: users.models.User :returns: Dictionary of serialized mentee data. :rtype: dict Example:: >>> serialize_mentee(mentee_user) { 'email': 'mentee@g.ucla.edu', 'name': 'Jane Doe', 'major': ['Biology'], 'minor': [], 'year': 1, 'hobbies': 'hiking', 'clubs': 'Pre-Med Society', 'goals': 'Become a doctor', 'specialCategories': ['firstgen', 'transfer'] } """ return { 'email': mentee.email, 'name': full_name(mentee), 'major': mentee.major, 'minor': mentee.minor, 'year': mentee.year, 'hobbies': mentee.hobbies, 'clubs': mentee.clubs, 'goals': mentee.goals, 'specialCategories': special_categories(mentee), }
[docs] def full_name(user): """ Derive a display name from a user's ``firstName`` and ``lastName`` fields. Strips whitespace from each component before joining. Falls back to ``'Not provided'`` if both fields are blank or absent, ensuring the return value is always a non-empty string suitable for display. :param user: The user whose name is being formatted. :type user: users.models.User :returns: Full name string, or ``'Not provided'`` if both name fields are empty. :rtype: str Example:: >>> full_name(user) # both fields set 'Jane Doe' >>> full_name(empty_user) # both fields blank 'Not provided' """ first = (user.firstName or '').strip() last = (user.lastName or '').strip() return f"{first} {last}".strip() or 'Not provided'
[docs] def special_categories(user): """ Return a list of background category labels that apply to the given user. Iterates over :data:`SPECIAL_CATEGORY_FIELDS` and includes the label for each field whose value is truthy on the user instance. Fields absent from the user object are treated as ``False`` via ``getattr`` default. To add or remove a category from API responses, update :data:`SPECIAL_CATEGORY_FIELDS` — no changes to this function are needed. :param user: The user whose background flags are being evaluated. :type user: users.models.User :returns: List of label strings for all truthy background fields. Returns an empty list if no flags are set. :rtype: list[str] Example:: >>> special_categories(user) # firstgen and transfer flags set ['firstgen', 'transfer'] >>> special_categories(user) # no flags set [] """ return [ label for field, label in SPECIAL_CATEGORY_FIELDS.items() if getattr(user, field, False) ]