-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support source='some_method' for HyperlinkedRelatedField. #2690
Support source='some_method' for HyperlinkedRelatedField. #2690
Conversation
Sorry I must be missing something - didn't understand why that'd be something we want/need to support? |
A callable The use case is simple. Fore example, you have a model class Conversation(models.Model):
provider = models.ForeignKey(Person)
requester = models.ForeignKey(Person)
sender = models.ForeignKey(Person) # enforced logically to be one of (provider, requester)
def get_recipient(self):
if self.sender == self.provider:
return self.requester
else:
return self.provider
class ConversationSerializer(serializers.ModelSerializer):
sender = serializer.HyperlinkedRelatedField(view_name=...)
recipient = serializer.HyperlinkedRelatedField(source='get_recipient', view_name=...) Basically If we don't want to support this we should at least add this to the docs that a related field can be used only on actual relations and not on methods that return a relation. Thanks! |
Isn't my example a valid use case? |
Yup - I'd agree that this is valid. |
Next steps to progress this issue:
|
(And apologies for the delay! Getting seriously back on the triaging bandwagon now) |
6b63439
to
16508cf
Compare
6b54703
to
47a22a5
Compare
@tomchristie I added a test case for PK relations and also a possible fix to show where the problem was introduced (it was working on DRF<3.x) To answer your questions:
|
Okay, seems reasonable enough. Given the narrow scope of the change, I feel like the test changes (eg changing the test model) are more detrimental than we'd like. I'd suggest that we either: (1) try to limit the test scope so that eg the model they use is contained in the test itself. Or (2) just drop the tests - the code is clearly more correct that it was previously, and even just a code comment of Either (1) or (2) would be acceptable to me. (Motivation for keeping the test scope limited is that we may one day want to refactor and clean up the gnarly relational tests, and right now this'd add more work to achieving that) |
ccf77ca
to
0386a01
Compare
@tomchristie I usually prefer tests over code comments, but in this case I just dropped the tests. It felt wrong to duplicate the two related models and have them self-contained in each test case. I removed the model changes and the tests, and added a code comment on the edge case. Please take another look. |
return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1])) | ||
|
||
# Handle edge case where the relationship `source` argument | ||
# points to a `get_relationship()` method on the model |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment should probably go instead the "if" block.
Great. Minor comments inline, but otherwise good to go. This level of most-minimal-possible incremental change is absolutely my preferred way to see pull requests. Tiny and self-evidentally correct, sensible changes. :) |
I moved the code comments and cleaned-up the whitespace. |
Perfect. |
Currently you cannot use a callable source for a
HyperlinkedRelatedField
. I added a test to reproduce the issue.The problem comes from the
PKOnlyObject
optimization. Thevalue
passed to the serialization method (here) is aPKOnlyObject
instance on which thepk
attribute is the callable configured as the source. Because of that, the URL reversal fails.Am I trying to do something illegal? I'm happy to fix the issue if we confirm this is a valid case that is failing.
Thanks!