Skip to content
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

Respect to_field property of ForeignKey relations #2435

Closed
wants to merge 15 commits into from

Conversation

Harper04
Copy link

Closes #2426.

This implementation just changes the Field class to SlugRelatedField and passes the to_field around (ultimately saving it to slug_field)

I also added a little optimization to SlugRelatedField i have to use. I get a recursive loop for my little use case because of the validation and loading of foreign models. But i am happy to remove it.

Testcases:
627 passed, 1 warnings in 5.12 seconds

Be gentle - it is my first contribution on github :)

Uses the SlugRelatedField instead.

SlugRelatedField will only get the Slugfield from the ORM as it does not need the other stuff
# Some tests do not have the full QuerySet API
# But we optimize SlugRelatedFields by only loading what we need

# it seems that some tests/django initializers are setting
# to_field where it is totally unnecessary so SlugRelatedField was used… Added checks
kwargs = get_relation_kwargs(field_name, relation_info)
to_field = kwargs.get('to_field', False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just do kwargs.pop('to_field', False) here instead of getting it, and then popping it on the next line?

@tomchristie tomchristie changed the title #2426 Respect to_field property of ForeignKey relations Respect to_field property of ForeignKey relations Jan 20, 2015
@@ -124,10 +135,17 @@ def _get_reverse_relationships(opts):
reverse_relations = OrderedDict()
for relation in opts.get_all_related_objects():
accessor_name = relation.get_accessor_name()
# For < django 1.6
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 confused by the For < django 1.6 comment - is the meaning there that to_field is only supported in 1.6+?

We always wrap any version branching behavior in compat.py so you probably want to create a helper function in there named get_to_field(field) or similar, and put this logic there.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests where failing on Travis for django versions below 1.6 and after a quick search i couldnt find to_field there so i assumed it was introduced in Django 1.6.

A little more searching shows that it was there but it is the other way around:
it was named to_field and later on mutated to to_fields as an array

https://github.com/django/django/blob/stable/1.4.x/django/db/models/fields/related.py
https://github.com/django/django/blob/stable/1.7.x/django/db/models/fields/related.py

That makes me also concerned about defaulting to index zero
Casual ForeignKeys shouldnt be a problem. They are giving a single to_field to their super class on initialization. But i found a few testcases in django related to ForeignObjects and Generics
https://github.com/django/django/search?utf8=%E2%9C%93&q=to_fields

@tomchristie
Copy link
Member

Some inline comments. Seems to be on the right track!

* Moved compatibility check of to_fields to compat.py
* Expanded the check with a way that should work on django <1.6. Need to check trevis after pushing..
@@ -303,7 +303,7 @@ def __init__(self, slug_field=None, **kwargs):

def to_internal_value(self, data):
try:
return self.get_queryset().get(**{self.slug_field: data})
return self.get_queryset().only(self.slug_field).get(**{self.slug_field: data})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure the only optimization is unrelated and should be removed.

return field.to_fields[0] if len(field.to_fields) else None
else:
def get_to_field(field):
return field.to_field
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still have to work on that one. Reading some more of that old code.

@Harper04
Copy link
Author

I've updated the pull request as i upgraded to the latest DRF Version and ran into some problems.
Are there any problems left with this patch? I am using it since a few months for now and didnt experienced any bugs related to this.

By the way:
I noticed that without this patch even a SlugRelatedField wont work for PUT Requests ([wrong type: expected pk but got unicode]) in some cases. Maybe i'll write a testcase or a demo project if i have more time in a few weeks.

@xordoquy xordoquy added this to the 3.1.4 Release milestone Jun 9, 2015
@xordoquy
Copy link
Collaborator

xordoquy commented Jun 9, 2015

I'll tend to think it's there. Any last minute comment about this one ?

@xordoquy xordoquy modified the milestones: 3.1.4 Release, 3.1.5 Release Jul 16, 2015
@vstoykov
Copy link
Contributor

@Harper04 can you rebase your PR with master because there are some conflicts.

@tomchristie tomchristie modified the milestones: 3.1.5 Release, 3.2.1 Release Jul 30, 2015
@tomchristie tomchristie modified the milestone: 3.2.1 Release Aug 7, 2015
@tomchristie
Copy link
Member

Superseded by #3526.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Respect to_field property of ForeignKey relations
5 participants