1) Only return field instancesthe current implementation has a common return pattern: (field_object, model, direct, m2m). After a few tests I realized that model, direct, m2m and field_name are all redundant and can be derived from only field_object. Since there are only 3-4 places that actually use direct and m2m it makes sense to remove this function from the new API spec.Here I show how all the information can be derived form field_instance (https://gist.github.com/PirosB3/6cb4badbb1b8c2e41a96/revisions), I ran the entire test suite and things look good. The only issue I can see now is from a performance point of view.2) Provide only 2 API endpoints- get_fields(types, opts) -> (field_instance, field_instance, ...)- get_field(field_name) -> field_instanceThe rest is all (I might be very wrong! don't trust me) redundant. By continuing with this iterative approach, I will soon find out if I am correct or not ;)
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/78f45c61-9626-4aa9-a854-64b11ba44572%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--Aymeric.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsub...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/445fea1d-406c-4ae9-b869-c02f189a2b86%40googlegroups.com.
--Aymeric.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscrib...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/78f45c61-9626-4aa9-a854-64b11ba44572%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
get_fields(types, opts) -> (field, field, ...)get_field(field_name, include_related=False, **kwargs) -> field
log = Log.objects.get(pk=1)log.get_fields(concrete=True, m2m=True, related=True)
log.get_field('log_level') # we're being explicit about the field name, no need for options
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/7496ef6d-4e88-41f4-b2b8-1bd2efa96aea%40googlegroups.com.
Excellent work, well done. I have a couple of questions/ideas though.1. The use of bit flags irks me. Would it be possible just to use numerous keyword arguments to the new get_fields ?
2. Since you've reduced the API to effectively two functions (get_fields, get_field), is it still necessary to contain those methods on an inner object? Can't the new methods live directly on the model? If they can't be put directly on the model for some reason, I would consider a better name than "meta". I can't think of a reason that the name meta should be used other than history. If you were to think about the purpose of the API without the associated history, what would you call it?
- Started on my GMail StoreWhile I was waiting for review, I have started an implementation of my GMail store. The implementation is documented here (https://docs.google.com/document/d/1yp2_skqkxyrc0egdRv6ofnRGCI9nmvxDFBkCXgy0Jwo/edit#heading=h.wyxx4xxijubt) and will be my final deliverable.So far, I have had some interesting results. With very little code, and the new Options API, I didn't have to modify a single file inside Django for my implementation to work. All code just overrides some of the main Django classes (Manager, Query, QuerySet).Currently, I have managed to:
- Browse my GMail threads through Django admin
- View a single GMail thread
- Read an entire email!
- Use the Console to do everything said above!
I have attached a picture.The next step is to improve my implementation. I will be (hopefully) soon releasing a GitHub project that you will be able to use to browse, read and send your mail through Django admin and forms!
On Fri, Jul 18, 2014 at 7:32 PM, Daniel Pyrathon <pir...@gmail.com> wrote:
- Started on my GMail Store
(...)
Pirosb3, just three words: really nice work!
Manipulating lists inappropriately can cause cache errorsAs lists can be manipulated, this can cause a series of issues. get_fields stores results in cache for efficiency, if the results are then manipulated on the "outside" this will directly manipulate the cache results stored. A solution to this is to always provide a "copy" of the cache, but after doing some cProfile I found out that copy is the second most expensive call throughout all operations.As this is a public API, it brings us to a design decision: do we want to prioritise performance and document that fields results should be never manipulated or should we return a copy? There are pros and cons of each aspect, and I will be discussing with Russell tomorrow.
Removed concrete fieldsTechnically speaking, concrete fields are data fields without a column. The only concrete field in the codebase is ForeignObject. There are 2 classes that inherit from ForeignObject: GenericRelation and ForeignKey, but each of them fall into different categories (virtual and data). Given that ForeignObject is an internal structure, and given that Django only looks for concrete fields on very few occasions, it makes sense to remove include_concrete from get_fields options.
Removed include_proxy optionIn only 2 parts of the codebase (deletion.py) we want to fetch all related objects for a model, including any relations to proxies of that model. This is used in order to perform a "bubble up" delete of relations (an example of this can be seen at https://github.com/django/django/blob/master/tests/delete_regress/tests.py#L209). Given that most developers will not need this option, and given that it can be easily computed from the outside, it makes sense to remove it from the get_fields options.
1) get_fields should return a list instead of a tuplePreviously, get_fields would return a tuple. The main reason was related to memory and immutability. After discussing with Russell, we decided this endpoint should actually return a list as it is a more suited data structure.
2) Move tree cache out of the apps registryThe main optimisation for the new API (described here https://code.djangoproject.com/wiki/new_meta_api#Mainoptimizationpoints) is currently storing information on the Apps registry. After discussing with Russell we agree this shouldn't be the correct place to keep this.
A solution is to store related fields information separately on each model (https://github.com/PirosB3/django/pull/5/files#diff-98e98c694c90e830f918eb5279134ab9R275). This has been done, and all tests pass.Unfortunately, there are performance implications with this approach: we are storing a new list on each model regardless of if it has related fields or not. I will be discussing with Russell about performance tomorrow.
3) Revisiting field types and options
Last week I opened this: https://groups.google.com/forum/#!topic/django-developers/s2Lp2lTEjAE in order to discuss with the community possible new field and option names. This week I have actually revisited the fields and options for get_field/s and I have come up with the following: (…)
On 3 août 2014, at 15:11, Daniel Pyrathon <pir...@gmail.com> wrote:1) get_fields should return a list instead of a tuplePreviously, get_fields would return a tuple. The main reason was related to memory and immutability. After discussing with Russell, we decided this endpoint should actually return a list as it is a more suited data structure.Can you clarify the reasons for this choice? If it’s just the purity of using the “proper” data type, I’m not sure it beats the practicality of returning an immutable iterable and avoiding the cost of a copy or the risk of incorrect manipulation.
The bugs that would occur if the cached value is altered inadvertently could be very hard to track down.
2) Move tree cache out of the apps registryThe main optimisation for the new API (described here https://code.djangoproject.com/wiki/new_meta_api#Mainoptimizationpoints) is currently storing information on the Apps registry. After discussing with Russell we agree this shouldn't be the correct place to keep this.+1A solution is to store related fields information separately on each model (https://github.com/PirosB3/django/pull/5/files#diff-98e98c694c90e830f918eb5279134ab9R275). This has been done, and all tests pass.Unfortunately, there are performance implications with this approach: we are storing a new list on each model regardless of if it has related fields or not. I will be discussing with Russell about performance tomorrow.Is the extra cost incurred only at start up ? How large is it? If it isn’t too bad and and run time performance is unchanged, it could be acceptable.
3) Revisiting field types and optionsLast week I opened this: https://groups.google.com/forum/#!topic/django-developers/s2Lp2lTEjAE in order to discuss with the community possible new field and option names. This week I have actually revisited the fields and options for get_field/s and I have come up with the following: (…)The latest iteration looks clear, consistent and straightforward. I like it.
--Aymeric.
On 4 August 2014 16:14, Daniel Pyrathon <pir...@gmail.com> wrote:But why? What's the benefit over using a tuple? ImmutableList is not
> Hi All,
>
> This has been resolved by using the ImmutableList datastructure
>
> https://github.com/PirosB3/django/blob/soc2014_meta_refactor_upgrade_flags_get_field_tree/django/db/models/options.py#L629
>
even a list, because it inherits from tuple.
Communication.From a purist theoretical perspective, there shouldn't be any argument - the data we're talking about is a list. Lists have homogeneous elements; Tuples have heterogeneous elements, but have *positional* homogeneity. A "Point" is a tuple, because element 0 of the tuple "means" the x coordinate. A Database row is a tuple - The first element is the primary key (an integer), second is the "name" column (a string), and so on.A tuple is *not* "just an immutable list".
> This has been resolved by using the ImmutableList datastructure
Looks fine. Behaviourally it's the same as a tuple, but with more explicit errors if you attempt to modify it, which seems reasonable.Given that `.get_fields()` and `.fields` return `ImmutableList`, presumably `.field_names`, `.concrete_fields` and `.local_concrete_fields` should do as well right?
- get_field(data=True, m2m=True) > 60% of the occurrences
- get_field(data=True, m2m=True, related_objects=True, related_m2m=True, virtual=True) > 39.9% of the occurrences
- get_field(data=False, m2m=True) once only! (0.01% of occurrences).
Benefits: