Summary
The API exposes a person's current_title but not their school, and the project-people endpoint exposes a person's project role but not the title/school they held while on the project. Both are already on the Position model — this is a serializer change only, no new model fields and no migration.
Why
Project Sidewalk's new About page (ProjectSidewalk/SidewalkWebpage#4664) hydrates its whole team section from this API so the roster never has to be hand-maintained. Two things it can't render today:
- Affiliations on the current-team cards. Right now a card can say "PhD Student" but not "University of Washington", so there's no way to show "Easterseals" for Judy Shanley or "University of Illinois Chicago" for Yochai Eisenberg. On a page that describes Project Sidewalk as a UW + UIC collaboration, unlabeled affiliations are a real gap.
- Credentials in the all-contributors roll call. The page names all ~150 people who have contributed, and we want each annotated with what they were at the time — "Undergrad, UMD", "High School Student, UW". This is the experiential-learning story the section exists to tell.
For (2) the current title is the wrong value: a 2015 undergraduate's profile now shows whatever they do today. It has to be the title held during that project stint.
The About page degrades gracefully — every one of these renders nothing when absent — so there's no breakage today and no rush. It just stays less informative until these land.
Proposed changes
Both use existing model helpers, so the implementation is a few lines each.
1. PersonSerializer — add current_school
Person.get_current_school is already a cached_property sitting right next to get_current_title, which the serializer already exposes. Mirroring it:
current_school = serializers.SerializerMethodField()
def get_current_school(self, obj):
# Person.get_current_school is a cached_property, not a method.
return obj.get_current_school
Adding current_department alongside it would be free (Person.get_current_department exists too) — useful to others even if the About page doesn't need it.
2. ProjectRoleSerializer — add title and school_abbreviated
ProjectRole already carries person, start_date, and end_date, so the matching Position is the person's position overlapping that stint. Position already has title (from the Title choices) and get_school_abbreviated().
The Title choices are exactly the vocabulary the roll call wants — High School Student, Undergrad, MS Student, PhD Student, Post doc, Research Scientist, Professor, and so on.
The abbreviation matters for the roll call specifically: it's a dense 3-column name list, so "UMD" works where "University of Maryland" would wrap every entry.
Where a stint spans multiple positions (an undergrad who stayed on for an MS), picking the one that overlaps the start of the project role seems most faithful to "what they were when they joined" — but I don't have a strong opinion, and whatever's most natural for the model is fine.
Field naming
I've matched the existing API conventions (current_title → current_school; Position.title → title). Happy to consume whatever names you prefer — just say so on this issue and I'll adjust the consumer, which is a one-line change on our side.
Consumer
public/js/aboutPage.js in ProjectSidewalk/SidewalkWebpage, covered by test/js/aboutPage.test.js, which pins the payload shapes of /api/v1/projects/sidewalk/people/, /api/v1/people/<url_name>/, /api/v1/projects/sidewalk/publications/, and /api/v1/projects/sidewalk/grants/. If any of those shapes change, those tests are where it'll surface.
Unrelated data-entry note
Two small things I noticed while integrating, both fixable in the admin rather than in code:
- The per-project
role is blank for 7 of the 9 people currently active on Project Sidewalk, so their role line falls back to current_title — which is why the page reads "Director" for Judy Shanley rather than anything about her role on the project.
- At least one grant has the literal string
"None" as its grant_id (a leaked Python None), which the About page special-cases so it doesn't render "(#None)".
Summary
The API exposes a person's
current_titlebut not their school, and the project-people endpoint exposes a person's projectrolebut not the title/school they held while on the project. Both are already on thePositionmodel — this is a serializer change only, no new model fields and no migration.Why
Project Sidewalk's new About page (ProjectSidewalk/SidewalkWebpage#4664) hydrates its whole team section from this API so the roster never has to be hand-maintained. Two things it can't render today:
For (2) the current title is the wrong value: a 2015 undergraduate's profile now shows whatever they do today. It has to be the title held during that project stint.
The About page degrades gracefully — every one of these renders nothing when absent — so there's no breakage today and no rush. It just stays less informative until these land.
Proposed changes
Both use existing model helpers, so the implementation is a few lines each.
1.
PersonSerializer— addcurrent_schoolPerson.get_current_schoolis already acached_propertysitting right next toget_current_title, which the serializer already exposes. Mirroring it:Adding
current_departmentalongside it would be free (Person.get_current_departmentexists too) — useful to others even if the About page doesn't need it.2.
ProjectRoleSerializer— addtitleandschool_abbreviatedProjectRolealready carriesperson,start_date, andend_date, so the matchingPositionis the person's position overlapping that stint.Positionalready hastitle(from theTitlechoices) andget_school_abbreviated().The
Titlechoices are exactly the vocabulary the roll call wants —High School Student,Undergrad,MS Student,PhD Student,Post doc,Research Scientist,Professor, and so on.The abbreviation matters for the roll call specifically: it's a dense 3-column name list, so "UMD" works where "University of Maryland" would wrap every entry.
Where a stint spans multiple positions (an undergrad who stayed on for an MS), picking the one that overlaps the start of the project role seems most faithful to "what they were when they joined" — but I don't have a strong opinion, and whatever's most natural for the model is fine.
Field naming
I've matched the existing API conventions (
current_title→current_school;Position.title→title). Happy to consume whatever names you prefer — just say so on this issue and I'll adjust the consumer, which is a one-line change on our side.Consumer
public/js/aboutPage.jsin ProjectSidewalk/SidewalkWebpage, covered bytest/js/aboutPage.test.js, which pins the payload shapes of/api/v1/projects/sidewalk/people/,/api/v1/people/<url_name>/,/api/v1/projects/sidewalk/publications/, and/api/v1/projects/sidewalk/grants/. If any of those shapes change, those tests are where it'll surface.Unrelated data-entry note
Two small things I noticed while integrating, both fixable in the admin rather than in code:
roleis blank for 7 of the 9 people currently active on Project Sidewalk, so their role line falls back tocurrent_title— which is why the page reads "Director" for Judy Shanley rather than anything about her role on the project."None"as itsgrant_id(a leaked PythonNone), which the About page special-cases so it doesn't render "(#None)".