-
Notifications
You must be signed in to change notification settings - Fork 211
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
Join style queries for dict, set, list, and embedded fields #178
base: master
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,35 @@ | |||
from django.conf import settings |
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.
None of the code in this file seems to be used anywhere. Am I missing something?
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 copied utils.py from the other tests. It's in aggregations, contrib, embedded, etc... It appears that it sets up a custom version of TestCase with some extra debugging support (settings.DEBUG = True). I didn't go deeply into what it does, but wanted to model my tests after the existing ones.
So I looked over the code and made some comments above, but as I looked more closely this reminded me of the A queries that are marked as deprecated. Its in django_mongodb_engine/query.py. It seems to do a similar thing. Have you looked at those? |
Thanks for the comments, Alex. I pushed up your recommended changes. Regarding the A() query, I did look at that originally. It unfortunately has quite a few issues. The syntax mixes Django and MongoDB styles. The Django part uses "__" and "=" while the MongoDB part uses "." and "," The Django part resolves db_columns from the models while the MongoDB part requires you to know the column names. You also run into issues when specifying a field more than once. For example, the following will return results with letters "abc" because the second exclude overwrites the first on f_dict...
With the changes I’ve proposed, you can write your query in standard Django format, taking into account all of the db_columns and field types, and using the normal Django query methods (exact, contains, in, etc...). For example...
|
Ok, I see the difference. My concern with your approach, which otherwise seems well-written, is that it adds extra fake fields to the model. I don't have a specific case where this breaks things but it seems like it likely would cause problems, for example if there are name conflicts or if some other code is inspecting the model and finding all these extra fields. I think you can create a two-part solution which addresses these issues:
Does that make sense? |
Let me think a bit about your concerns to make sure they are addressed. I'm not a fan of the One thing to note is that the extra fields are only added when a query is made on a child field of a MongoDB Toolbox field types. Since a period is not a valid character for a normal field name, and a period is always present in a child field name, there isn't any chance of field name collision. Also, this code is a no-op if the caller never makes a child field query. But one area I think could be improved is hiding the extra field a bit better. They need to be part of the query, since Django's code expects to be able to resolve a query key into field information. But I agree with you that it would be nice if the app didn't know about this. I'll think about that last point a bit more. Thank you again for taking the time to look this over and comment. On a side note, I was able to fix the embedded model foreign key lookup in 1.6. |
So I did some research and experiments this weekend. What I found was Django itself does a similar technique for internal fields, specifically with the
Hopefully this addresses your concerns. If there is a more specific case where you see an issue, please let me know. |
There is a bug in _maybe_add_dot_field function. If you use "icontains" operator, when the code is checking if exist a operator in the query, the operator "contains" pass in if name.endswith(op) but then, in re.sub function, the string is not replace. Then, the break command finish de for cycle. You need to delete the break line. Example: If you use the query "alumn__name__icontains" Without break line
|
Hi Manuel,Thanks for the message. I fixed the code so it matches endswith(LOOKUP_SEP + op), so it doesn't confuse icontains and contains.Brian -------- Original Message --------
—Reply to this email directly or view it on GitHub. |
Can you update the pull request with the fix? |
Hi Alex. The pull request should include the fix now. Let me know if you see any issues. |
This is great, I try to avoid using dict, set, list, and embedded fields mostly because of executing/using Why it's not merged into master yet ? |
This change adds the ability to query (get, filter, exclude) on DictField, SetField, ListField, and EmbeddedModelField using join style syntax.
For example...
MyModel.objects.filter(myfield__one__two__exact='something').exclude(myfield__three='something')
Which would filter on myfield.one.two and exclude myfield.three in MongoDB.