I have a point C and a Linestring AB, both with SRID 4326. I'd like to find the perpendicular projection of C onto B, which would be point D.

I currently have a 2D implementation of this perpendicular projection using unit vectors. But it does not return the correct point on a world map (as it is 2D). Found here: Perpendicular on a line segment from a given point
I have thought of two ways to do this with PostGIS:
1) Create a line from C to point E, where CE is parallel to AB. Then rotate CE 90 degrees around C and find the intersection, which should be D.
2) Find a bearing and distance method similar to the Google Maps geometry library here (the computeOffset method: https://developers.google.com/maps/documentation/javascript/geometry
How would I do this with the GeoDjango methods. It does not seem to expose the ST_AZIMUTH or ST_ROTATE?
It also seems like using raw SQL in GeoDjango would be an antipattern. But in this case, it seems like I need more granular control than what the GeoDjango API allows.
Any help would be appreciated.