The canonical way to do this with pip was using Constraints Files [1]. When you pollute your main requirements.txt it gets harder to see which package is an actual dependency of your project, and which ones are just sub-dependencies. Constraint files also let you not install a package if it's no longer a sub-dependency.
That being said, the uv experience is much nicer (also insanely fast).
[1] https://pip.pypa.io/en/stable/user_guide/#constraints-files