-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Don't raise 500 errors when filter query parameter matches a model property name. #7609
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
Don't raise 500 errors when filter query parameter matches a model property name. #7609
Conversation
rest_framework/filters.py
Outdated
if ( | ||
not getattr(field, 'write_only', False) and | ||
not field.source == '*' and ( | ||
field_name in model_field_names or field.source in model_field_names |
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.
I'm not convinced this is necessarily correct. For example we allow sources such as author.name
, which will reference the name
field across the relationship author
, but that'd be filtered out by this new check, right?
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.
Yes, you are right, I have missed that. 😕 What about the following solution:
model_class = queryset.model
model_property_names = [
# "pk" is a property added in Django's Model class, however it is valid for ordering.
attr for attr in dir(model_class) if isinstance(getattr(model_class, attr), property) and attr != 'pk'
]
return [
(field.source.replace('.', '__') or field_name, field.label)
for field_name, field in serializer_class(context=context).fields.items()
if not getattr(field, 'write_only', False) and not field.source == '*'
if (
not getattr(field, 'write_only', False) and
not field.source == '*' and
field_name not in model_property_names and
field.source not in model_property_names
)
]
or do you have any other suggestions?
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.
That looks okay to me, I think? (Although probably just need field.source not in model_property_names
, rather than field_name not in model_property_names
?)
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.
Oh I didn't know that field.source
is field_name
by default, you are totally right then! 🚀 I think that the comment line about pk
should stay, what do you think? After we decide this I will make the related changes. 👍🏼
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.
Yes the PK comment makes sense to me.
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.
Pushed related changes: c7f8b14. If you have any other concerns we may further discuss. Thank you for your time! 🙏🏼
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.
I think I'm okay with this. Anyone else want to chime in before we merge this?
Great, thanks. |
My pleasure! 🎉 |
* Add failing tests for ordering filter with model property * Fix get_default_valid_fields of OrderingFilter * Filter model properties in get_default_valid_fields of OrderingFilter
* Add failing tests for ordering filter with model property * Fix get_default_valid_fields of OrderingFilter * Filter model properties in get_default_valid_fields of OrderingFilter
Fixes: #7608
What is in this PR:
description
added to theOrderingFilterModel
OrderingFilterSerializerWithModelProperty
which includes all fields ofOrderingFilterModel
and the model propertydescription
.test_ordering_without_ordering_fields
with two passingassert
statements to see using model properties on a serializer withOrderingFilter
doesn't have any side effect.OrderingFilter.get_default_valid_fields()
method which basically checks if thefield_name
orfield.source
is inmodel_field_names
field.source
is inmodel_property_names
(c7f8b14).