Skip to content

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

Conversation

omerfarukabaci
Copy link
Contributor

@omerfarukabaci omerfarukabaci commented Oct 22, 2020

Fixes: #7608

What is in this PR:

  • A model property called description added to the OrderingFilterModel
  • Created OrderingFilterSerializerWithModelProperty which includes all fields of OrderingFilterModel and the model property description.
  • Failing test has been added under test_ordering_without_ordering_fields with two passing assert statements to see using model properties on a serializer with OrderingFilter doesn't have any side effect.
  • A solution has been added to OrderingFilter.get_default_valid_fields() method which basically checks if the field_name or field.source is in model_field_names field.source is in model_property_names (c7f8b14).

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
Copy link
Member

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?

Copy link
Contributor Author

@omerfarukabaci omerfarukabaci Mar 10, 2021

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?

Copy link
Member

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?)

Copy link
Contributor Author

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. 👍🏼

Copy link
Member

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.

Copy link
Contributor Author

@omerfarukabaci omerfarukabaci Mar 11, 2021

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! 🙏🏼

Copy link
Member

@tomchristie tomchristie left a 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?

@tomchristie tomchristie merged commit ce15683 into encode:master Mar 16, 2021
@tomchristie
Copy link
Member

Great, thanks.

@tomchristie tomchristie changed the title Ordering filter bug with model property serializer field Don't raise 500 errors when filter query parameter matches a model property name. Mar 16, 2021
@omerfarukabaci
Copy link
Contributor Author

My pleasure! 🎉

stefanacin pushed a commit to stefanacin/django-rest-framework that referenced this pull request Mar 22, 2021
* 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
@tomchristie tomchristie mentioned this pull request Mar 25, 2021
sigvef pushed a commit to sigvef/django-rest-framework that referenced this pull request Dec 3, 2022
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Don't raise 500 errors when filter query parameter matches a model property name.
2 participants