Hi Russ,
Thanks for the feedback!
I believe the proposed code already addresses points 1-4.
1) The implementation does in fact return the correct natural key, `(self.username,)`, for the User model.
2) When multiple fields have `unique=True`, the implementation does not choose from among them; it returns a tuple containing *all* non-auto-generated unique fields.
3) In the presence of multiple `unique_together` tuples, the implementation arbitrarily chooses the first one.
4) In the presence of both `unique_together` fields and `unique` fields, the implementation arbitrarily goes with the former.
You can see the specific algorithm at
line 1422.
The implementation always chooses a natural key which uniquely identifies the relevant model. The choice may be arbitrary in the presence of multiple cues, but so is any individually-implemented choice of a natural key.
At the very worst, if the user does not agree with the choice for the specific model, they can fall back to individually implementing the natural key for that model; this is no worse than the current situation. So I would argue that the base implementation proposed here is strictly better than the status quo.
In the course of serializing about a dozen different models, I've found this to be a very useful base implementation that has saved me from the tedium of writing many lines of boilerplate.