Re: Why not Single Table Inheritance?

2014-06-06 Thread Thomas Güttler



Am 26.05.2014 00:50, schrieb Craig de Stigter:

If you ignore STI, I think it is quite straightforward to solve this with a

parent model class which adds a type field, and manager methods to add the
select_related calls and "interpret" the type field properly; so I don't see an
immediate need for inclusion in core.

Well, you don't need select_related calls at all, if you're actually storing things 
in one table like "single-table
inheritance" implies.

I too was surprised to find Django doesn't do this, and was unable to find a 
good third-party app that does it.

So I wrote my own: https://github.com/craigds/django-typed-models/

It works well and we have been using it in production for a couple years.


...

Thank you very much for your answer.

I guess a lot of developers don't want to hear the next lines:

I think it is a "not invented here" syndrome: Ruby on Rails did it before. 
That's
a reason to do it different.

But I can live with an external library like django-typed-models. It does not 
need to be in django core.

There is a second fear: Some years ago, when I was new to database layout 
design I tried
to avoid to create new tables. And I guess a lot of other did it like this, 
too. If you
could use some tricky algorithm to avoid a database table, I choose to code, 
not to
use a new table.

Time has passed and I learned: Structure is more important, code can be 
replaced.

If I can write less code with a good database layout now, I prefer less code. 
Django
ORM and south handles new tables perfect.

New tables is an expansion in one dimension, the other dimension is: new 
columns.

That's what STI does: it creates a lot of new columns. When I first read how 
STI works,
I had the same old fear: New columns  that is outside my current comfort 
zone.

I want to use STI the next time I need model inheritance.

Regards,
  Thomas

--
Thomas Güttler
http://thomas-guettler.de/


--
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/539170D7.8090509%40tbz-pariv.de.
For more options, visit https://groups.google.com/d/optout.


Re: Why not Single Table Inheritance?

2014-06-06 Thread Russell Keith-Magee
On Fri, Jun 6, 2014 at 3:42 PM, Thomas Güttler  wrote:

>
>
> Am 26.05.2014 00:50, schrieb Craig de Stigter:
>
>  If you ignore STI, I think it is quite straightforward to solve this with
>>> a
>>>
>> parent model class which adds a type field, and manager methods to add the
>> select_related calls and "interpret" the type field properly; so I don't
>> see an
>> immediate need for inclusion in core.
>>
>> Well, you don't need select_related calls at all, if you're actually
>> storing things in one table like "single-table
>> inheritance" implies.
>>
>> I too was surprised to find Django doesn't do this, and was unable to
>> find a good third-party app that does it.
>>
>> So I wrote my own: https://github.com/craigds/django-typed-models/
>>
>> It works well and we have been using it in production for a couple years.
>>
>
> ...
>
> Thank you very much for your answer.
>
> I guess a lot of developers don't want to hear the next lines:
>
> I think it is a "not invented here" syndrome: Ruby on Rails did it before.
> That's
> a reason to do it different.
>

Poppycock.

Allow me to assure you that "What Rails Did" didn't even rate a sideways
mention during the design discussions for model inheritance. You can verify
this yourself with a bit of a search of the django-dev archives.

What *did* factor into the decision - the fact that, in the general case,
STI means you have to make almost all the fields in your model NULLable.
You lose any semblance of having an actual database schema, and end up
writing a whole lot of code to re-implement the features of a database
schema instead of using the well tested, robust implementation that the
database provides.

When Django's model inheritance features were added - over six years ago -
we made the decision to implement a solution that made the best usage of
database features, not to try and turn a database into an overweight
key-value store.

Yours,
Russ Magee %-)

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/CAJxq849xL-TJnr4BMmYJ9%2B_OWNh--pJswS0YJp-X-V%3D-hv2_LQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: Integrating polymorphic queries in the framework

2014-06-06 Thread Luis Masuelli
Don't know if it's a big patch at all. A polymorphic call could be like 
this:

1. Check if the class is polymorphic by itself or by inheritance:

Traverse the inheritance D-Graph (we have to remember it's not a tree 
anymore) starting from the current class - It would stop on (and not count) 
models.Model (abstract=True and proxy models are also not counted). It 
should stop on the first parent having a Meta definition as I exposed 
before.
Having multiple (concrete) ancestors defining a Meta like that, would raise 
an exception.
Defining such Meta while an ancestor already defined it, would raise the 
same exception.
Not finding such Meta in the dgraph would have no effect, and the entire 
process would be ignored (i.e. a norma query could be executed over the 
current model). It could alternatively throw an exception or leave it as a 
settings option (CONTENTTYPE_POLYMORPHIC_EXCEPTION = True #you get the idea)

2. If the Meta was found, the polymorphic query could be done. Traverse the 
models down from the initial model class (i.e. the one from which the PQ 
was done on) enumerating concrete and nonproxy models. Basing in your idea, 
a narrow=(Model1, Model2, ...) argument could be specified to only include 
those models in the list, ignoring the rest (and stopping when all those 
model classes were iterated and found). As complement, an exclude=(Model1, 
Model2) could be alternatively specified to skip those classes (as skipping 
proxy and abstract classes in the enumeration).

3. Perform a select_related or prefetch_related query with the enumerated 
classes. This would do a join or prefetch perhaps only on the classes of 
interest (narrow=/exclude=) instead of doing the biggest possible join.

An alternative could be that to define a polymorphic model, the parent 
model could be a brand new contenttypes.models.PolymorphicModel (itself 
being abstract=True) and the nearest concrete ancestors must implement such 
Meta attributes (or an exception should be throw). Perhaps this (abstract) 
model could have a metaclass defining a new Manager for 'objects' attribute 
which could generate a queryset implementing this polymorphic() method.

Such model could have the widely-mentioned get_real_instance (as in 
django-polymorphic) or narrow() as mentioned in the post. The 
implementation could vary: it starts by getting the current object's 
contenttype from the discriminator and get the model class for it. if 
narrow-style is implemented, issubclass() could be called to determine 
whether the object belongs to any of those classes and return the real 
instance if so (it could avoid loading a non-specified class lazily). 
implementing get_real_instance class could load lazily the class if was not 
specified.

As I see, an implementation like I described (which is not new at all) 
could let you leverage the polymorphism level and let you suffer the 
tradeoffs you choose.

Remember that, with this (rant-styled, but improved from reading the post 
you pointed me to) proposal, anyone could choose to use the polymorphism in 
the queries or not, by calling explicitly such method on the query. Not 
using it would behave as normal queries.



El jueves, 5 de junio de 2014 20:03:14 UTC-5, Russell Keith-Magee escribió:
>
>
> On Fri, Jun 6, 2014 at 6:49 AM, Luis Masuelli  > wrote:
>
>> What about integrating polymorphic features in the ORM? It's like having 
>> the features of django-polymorphic but in the core.
>>
>> The polymorphism could be acheved by:
>> 1. Having contenttypes installed (this is a common pattern).
>> 2. Specifying a root (first ancestor) model class like:
>>
>> class MyParentModel(models.Model):
>> ...
>>
>> class Meta:
>> polymorphic = True
>> discriminant = "somefield" #it could default to 
>> 'content_type' if not specified. This field could be created.
>>
>> To achieve the polymorphism a query could be like:
>>
>> objects = 
>> MyParentModel.objects.filter(foo=bar,baz=clorch,...).polymorphic().more().calls().ifneeded()
>>
>> Such method could complain if the contenttypes application is not 
>> installed; it could be based on many select_related() arguments (which are 
>> collected by tree-traversing the hierarchy, perhaps ignoring proxies).
>> Alternatively, this could be an util in the contenttypes app instead of 
>> the core apps:
>>
>> objects = 
>> contenttypes.utils.polymorphic(MyParentModel.objects.filter(foo=bar,baz=clorch,...)).more().calls().ifneeded()
>>
>> Sorry if this was posted before, but it's my first time here and I always 
>> asked why does Django not have this feature in the core.
>>
>
> If you set your time machine to go back 6 years, you'll find the original 
> discussions about model inheritance (implemented by Malcolm Tredinnick, and 
> I did a whole bunch of design/implementation review):
>
> https://groups.google.com/forum/#!topic/django-developers/fUCtNz6_qRI
>
> In those discussions, we discussed the idea o

LOCALE_PATHS should have a check to make sure it's a list/tuple

2014-06-06 Thread Tim Shaffer
I'm playing around with 1.7b4 and I was trying to track down why my app was 
not auto-reloading when files were changed using the dev server.

Turns out, it was an improperly configured LOCALE_PATHS setting.

My LOCALE_PATHS was configured like this:

LOCALE_PATHS = (
'/path/to/locale'
)

At first glance, it looks okay. But it's actually a string and not a tuple 
since it does not have a comma.

This causes a problem in the autoloader, here:

https://github.com/django/django/blob/608e6eb2959c6e56e5c702ca0d15fa0e6c2eef16/django/utils/autoreload.py#L98

This would be fine, but since LOCALE_PATHS is a string, calling 
basedirs.extend(LOCALE_PATHS) actually causes every character in the string 
to get appended to basedirs. Then it walks through the tree and tries to 
find .mo files. And since there are 3 slashes in the string, the autoloader 
attempts to search the root drive 3 times.

Bottom line is that having LOCALE_PATHS set to a string with slashes causes 
autoreloading to essentially take *forever*. 

Maybe adding a warning/validation to ensure LOCALE_PATHS is a list/tuple 
would be a good idea?

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/c6c18d71-5da5-4aaf-83e9-db3b2d86e430%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: LOCALE_PATHS should have a check to make sure it's a list/tuple

2014-06-06 Thread Tim Graham
Sure, patches welcome. `django.conf.__init__` already has some 
"tuple_settings" logic which is looks like would probably work for this.

On Friday, June 6, 2014 11:51:30 AM UTC-4, Tim Shaffer wrote:
>
> I'm playing around with 1.7b4 and I was trying to track down why my app 
> was not auto-reloading when files were changed using the dev server.
>
> Turns out, it was an improperly configured LOCALE_PATHS setting.
>
> My LOCALE_PATHS was configured like this:
>
> LOCALE_PATHS = (
> '/path/to/locale'
> )
>
> At first glance, it looks okay. But it's actually a string and not a tuple 
> since it does not have a comma.
>
> This causes a problem in the autoloader, here:
>
>
> https://github.com/django/django/blob/608e6eb2959c6e56e5c702ca0d15fa0e6c2eef16/django/utils/autoreload.py#L98
>
> This would be fine, but since LOCALE_PATHS is a string, calling 
> basedirs.extend(LOCALE_PATHS) actually causes every character in the string 
> to get appended to basedirs. Then it walks through the tree and tries to 
> find .mo files. And since there are 3 slashes in the string, the autoloader 
> attempts to search the root drive 3 times.
>
> Bottom line is that having LOCALE_PATHS set to a string with slashes 
> causes autoreloading to essentially take *forever*. 
>
> Maybe adding a warning/validation to ensure LOCALE_PATHS is a list/tuple 
> would be a good idea?
>

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/657a7af7-033b-4578-a843-baac56f24a5e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [RFC] Python 3 and MySQL

2014-06-06 Thread Collin Anderson
While we're on the topic, I'd like to propose (also?) supporting the 
pure-python, MySQLdb-compatible pymysql, which INADA Naoki (methane) has 
also put a lot of work into. 

pymysql is pure-python, so it's really easy to get up-and running on Mac OS 
X and in other environments, because you don't need the mysql header files 
around. Just pip install pymysql, and you're good to go.

https://code.djangoproject.com/ticket/22391

Tim says on the ticket: "One question I have is how we are going to ensure 
that it doesn't break if we merge it to core. Do we need another MySQL 
build to the Jenkins matrix?"

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/260d5b5e-47e3-4432-848f-b3fe58db1a7a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [GSOC] Weekly update

2014-06-06 Thread Daniel Pyrathon
Hi All,

Based on the work done last week, this week I have worked on the following:

*1) Covered the current _meta implementation of unittests*
The current Options is not covered by unit tests at all, I have created the 
model_options test module containing one or more unit tests for each 
endpoint and usage. Each endpoint is tested with many different models and 
fields (data, m2m, related objects, related m2m, virtual, ..). Each unit 
test asserts equality in field naming and field type. Endpoints that return 
the model are also tested for equality.

This branch is found here: 
https://github.com/PirosB3/django/tree/soc2014_meta_unittests

*2) Pulled in tests from soc2014_meta_unittests and tested the new 
implementation*
The previous branch that I developed on contains the new API 
implementation, I have pulled in the tests from soc2014_meta_unittests and 
I have switched the old API calls to the new API calls (with a few 
adjustments). I have successfully made all tests pass even though I have 
found some design issues that need to be addressed in my next update call.

This branch is found here: 
https://github.com/PirosB3/django/tree/soc2014_meta_refactor

*3) Created a new branch that maps the old implementation with the new*
Today I started putting my new API in "production". This is obviously 
nowhere near a finalised version but it helps me spot some edge cases that 
are not in the unit-tests. Each issue found has been converted into a 
standalone unit-test and has been proved to fail.
Unfortunately, this made me realise of other design issues related to the 
new return type of get_fields -> (field_name, field), A decision will be 
taken on monday.

This branch is found here: 
https://github.com/PirosB3/django/tree/soc2014_meta_refactor_implementation 
as is for personal use only

For any questions, let me know!
Dan
 

On Sunday, June 1, 2014 6:10:53 PM UTC+2, Daniel Pyrathon wrote:
>
> Hi All,
>
> An update on my side, some interesting work has happened this week: me and 
> Russell have decided to start on the implementation early in order to 
> understand better the internals of Options. Currently I am working on the 
> following:
>
> *Providing one single function: get_fields(types, opts, **kwargs)*
> Previously we had identified a number of functions that contained similar 
> data but had a different return type. We are going to provide one function 
> that takes a set of field types + options and returns the same output 
> everywhere: ((field_name, field), ...). This has the benefit of simplicity 
> and is more maintainable than the previous approach.
>
> TYPES = DATA, M2M, FK, RELATED_OBJECT, RELATED_M2M
> OPTS = NONE, LOCAL_ONLY, CONCRETE, INCLUDE_HIDDEN, INCLUDE_PROXY, VIRTUAL
>
> *Providing two functions for retrieving details of a specific field*
> As specified in my previous document, in many parts of the code we just 
> want to retrieve a field object by name, other times we have a field but 
> need other metadata such as: owner (model_class), direct (bool), m2m 
> (bool). We will provide two functions:
>
> get_field(field_name) -> field_instance
>
> get_field_details(field_instance) -> direct, m2m, (still to be defined)
>
> While we still have not entirely defined what *get_field_details *will 
> return, this will be done soon.
>
>
> *Building a test suite for the existing API*
> The new API development will be driven by a test suite that will compare 
> the current (legacy) API with the new implementation. While return types 
> will be different, we are asserting that all the correct fields and 
> metadata are returned. Building a test suite means we can start 
> implementing before a final API spec is finalised. It also means we can 
> iterate faster and, from my perspective, I also understand a lot more of 
> the current implementation. We are testing each combination of fields and 
> options together.
>
> My current implementation is visible here: 
> https://github.com/PirosB3/django/compare/soc2014_meta_refactor
>
> For any questions or suggestions, let me know.
>
> Daniel Pyrathon
>
>
> On Monday, May 26, 2014 1:28:31 AM UTC+2, Daniel Pyrathon wrote:
>>
>> Hi All,
>>
>> Just to make you know, I have put up the current _meta API documentation 
>> here:
>> http://162.219.6.191:8000/ref/models/meta.html?highlight=_meta
>> As always, feel free to ask questions.
>>
>> Daniel
>>
>> On Monday, May 26, 2014 1:26:27 AM UTC+2, Daniel Pyrathon wrote:
>>>
>>> Hi Josh,
>>>
>>> The meta API specified in the docs (
>>> https://github.com/PirosB3/django/blob/meta_documentation/docs/ref/models/meta.txt)
>>>  
>>> is the current API. I have documented this in order to understand more of 
>>> the current implementation and it will be good to show a comparison when a 
>>> new meta API will be approved.
>>>
>>> My current proposal (
>>> https://gist.github.com/PirosB3/371704ed40ed093d5a82) and it will be 
>>> discussed tomorrow with Russell. I will post as soon as I have updates.
>>>
>>> Daniel Pyr

Re: Why not Single Table Inheritance?

2014-06-06 Thread Shai Berger
Let me expand on Russell's expletives:

On Friday 06 June 2014 09:42:15 Thomas Güttler wrote:
> 
> I guess a lot of developers don't want to hear the next lines:
> 
> I think it is a "not invented here" syndrome: Ruby on Rails did it before.
> That's a reason to do it different.
> 

This does deserve calling out, because...

> 
> If I can write less code with a good database layout now, I prefer less
> code. Django ORM and south handles new tables perfect.
> 
> New tables is an expansion in one dimension, the other dimension is: new
> columns.
> 
> That's what STI does

No. If you're considering STI, then the "dimensions" are not orthogonal: STI 
is an attempt to use added columns _instead_ of added tables. It is, as has 
already been noted on this thread (by myself as well as others), a form of 
denormalization -- which means you may get some performance benefits out of it, 
but you are certain to lose important correctness guarantees.

So, asking for STI in the name of better database design is a little 
inconsistent; doing this while casting doubt on the honesty of other 
developers -- well, Russell gave a very succinct description of that.

Shai.

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/2746566.8l84GYph17%40deblack.
For more options, visit https://groups.google.com/d/optout.


Re: Why not Single Table Inheritance?

2014-06-06 Thread Aymeric Augustin
On 6 juin 2014, at 09:42, Thomas Güttler  wrote:

> I think it is a "not invented here" syndrome: Ruby on Rails did it before. 
> That's
> a reason to do it different.

The reason is more simple.

Rails was designed around MySQL, a database with a rather casual relationship
to data integrity. It will happily truncate data or save invalid values in the 
name of
performance. In the same spirit STI trades data integrity for speed. It avoids 
joins,
which can be very slow on MySQL, but also prevents the database from enforcing
constraints.

Django was designed around PostgreSQL, a database that cares about its data.

That explains many differences in the design of the Rails and Django ORMs.

-- 
Aymeric.




-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/E238DFA5-8938-4DBD-8E78-0D0B477ACA88%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.


Schema tests and test_foreign_key_index_long_names_regression

2014-06-06 Thread Maximiliano Robaina
Hi,

I'm trying to figured out how the 
test_foreign_key_index_long_names_regression method works.
For my (using firebird backend)  this test fails with:
   
   AssertionError: u'author_foreign_key_with_rea7ef8' not found in {u'ID': 
{'unique': False, 'primary_key': True}}

I see that It's using get_indexes to check if a foreign key field exist as 
index, but get_indexes returns a different information

What am I doing wrong here or am I misinterpreting something wrong?


---
Maxi

-- 
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-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@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/b3fbb833-d48d-4687-8e45-28b9bfb5fbb7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Integrating polymorphic queries in the framework

2014-06-06 Thread Curtis Maloney
Can I draw your attention to Sebastian Vetter's investigation of the
relative scalability of different model polymorphism approaches :
https://github.com/elbaschid/talks/tree/master/2013-12-12_MelbDjango_MTI.Performance

Basically, the "select_related then resolve" approach [used in
django-model-utils InheritanceManager] doesn't scale nearly as well as
django-polymorphic's more pre-fetch-related "1+N queries" approach.

--
Curtis


On 7 June 2014 01:00, Luis Masuelli  wrote:

> Don't know if it's a big patch at all. A polymorphic call could be like
> this:
>
> 1. Check if the class is polymorphic by itself or by inheritance:
>
> Traverse the inheritance D-Graph (we have to remember it's not a tree
> anymore) starting from the current class - It would stop on (and not count)
> models.Model (abstract=True and proxy models are also not counted). It
> should stop on the first parent having a Meta definition as I exposed
> before.
> Having multiple (concrete) ancestors defining a Meta like that, would
> raise an exception.
> Defining such Meta while an ancestor already defined it, would raise the
> same exception.
> Not finding such Meta in the dgraph would have no effect, and the entire
> process would be ignored (i.e. a norma query could be executed over the
> current model). It could alternatively throw an exception or leave it as a
> settings option (CONTENTTYPE_POLYMORPHIC_EXCEPTION = True #you get the idea)
>
> 2. If the Meta was found, the polymorphic query could be done. Traverse
> the models down from the initial model class (i.e. the one from which the
> PQ was done on) enumerating concrete and nonproxy models. Basing in your
> idea, a narrow=(Model1, Model2, ...) argument could be specified to only
> include those models in the list, ignoring the rest (and stopping when all
> those model classes were iterated and found). As complement, an
> exclude=(Model1, Model2) could be alternatively specified to skip those
> classes (as skipping proxy and abstract classes in the enumeration).
>
> 3. Perform a select_related or prefetch_related query with the enumerated
> classes. This would do a join or prefetch perhaps only on the classes of
> interest (narrow=/exclude=) instead of doing the biggest possible join.
>
> An alternative could be that to define a polymorphic model, the parent
> model could be a brand new contenttypes.models.PolymorphicModel (itself
> being abstract=True) and the nearest concrete ancestors must implement such
> Meta attributes (or an exception should be throw). Perhaps this (abstract)
> model could have a metaclass defining a new Manager for 'objects' attribute
> which could generate a queryset implementing this polymorphic() method.
>
> Such model could have the widely-mentioned get_real_instance (as in
> django-polymorphic) or narrow() as mentioned in the post. The
> implementation could vary: it starts by getting the current object's
> contenttype from the discriminator and get the model class for it. if
> narrow-style is implemented, issubclass() could be called to determine
> whether the object belongs to any of those classes and return the real
> instance if so (it could avoid loading a non-specified class lazily).
> implementing get_real_instance class could load lazily the class if was not
> specified.
>
> As I see, an implementation like I described (which is not new at all)
> could let you leverage the polymorphism level and let you suffer the
> tradeoffs you choose.
>
> Remember that, with this (rant-styled, but improved from reading the post
> you pointed me to) proposal, anyone could choose to use the polymorphism in
> the queries or not, by calling explicitly such method on the query. Not
> using it would behave as normal queries.
>
>
>
> El jueves, 5 de junio de 2014 20:03:14 UTC-5, Russell Keith-Magee escribió:
>
>>
>> On Fri, Jun 6, 2014 at 6:49 AM, Luis Masuelli 
>> wrote:
>>
>>> What about integrating polymorphic features in the ORM? It's like having
>>> the features of django-polymorphic but in the core.
>>>
>>> The polymorphism could be acheved by:
>>> 1. Having contenttypes installed (this is a common pattern).
>>> 2. Specifying a root (first ancestor) model class like:
>>>
>>> class MyParentModel(models.Model):
>>> ...
>>>
>>> class Meta:
>>> polymorphic = True
>>> discriminant = "somefield" #it could default to
>>> 'content_type' if not specified. This field could be created.
>>>
>>> To achieve the polymorphism a query could be like:
>>>
>>> objects = MyParentModel.objects.filter(foo=bar,baz=clorch,...).
>>> polymorphic().more().calls().ifneeded()
>>>
>>> Such method could complain if the contenttypes application is not
>>> installed; it could be based on many select_related() arguments (which are
>>> collected by tree-traversing the hierarchy, perhaps ignoring proxies).
>>> Alternatively, this could be an util in the contenttypes app instead of
>>> the core apps:
>>>
>>> objects = contenttypes.utils.

Re: Integrating polymorphic queries in the framework

2014-06-06 Thread Curtis Maloney
Hosted version of the talk:
http://www.roadside-developer.com/talks/2013-12-12_MelbDjango_MTI.Performance/#/

[Thanks, Brenton!]

--
Curtis



On 7 June 2014 11:52, Curtis Maloney  wrote:

> Can I draw your attention to Sebastian Vetter's investigation of the
> relative scalability of different model polymorphism approaches :
> https://github.com/elbaschid/talks/tree/master/2013-12-12_MelbDjango_MTI.Performance
>
> Basically, the "select_related then resolve" approach [used in
> django-model-utils InheritanceManager] doesn't scale nearly as well as
> django-polymorphic's more pre-fetch-related "1+N queries" approach.
>
> --
> Curtis
>
>
> On 7 June 2014 01:00, Luis Masuelli  wrote:
>
>> Don't know if it's a big patch at all. A polymorphic call could be like
>> this:
>>
>> 1. Check if the class is polymorphic by itself or by inheritance:
>>
>> Traverse the inheritance D-Graph (we have to remember it's not a tree
>> anymore) starting from the current class - It would stop on (and not count)
>> models.Model (abstract=True and proxy models are also not counted). It
>> should stop on the first parent having a Meta definition as I exposed
>> before.
>> Having multiple (concrete) ancestors defining a Meta like that, would
>> raise an exception.
>> Defining such Meta while an ancestor already defined it, would raise the
>> same exception.
>> Not finding such Meta in the dgraph would have no effect, and the entire
>> process would be ignored (i.e. a norma query could be executed over the
>> current model). It could alternatively throw an exception or leave it as a
>> settings option (CONTENTTYPE_POLYMORPHIC_EXCEPTION = True #you get the idea)
>>
>> 2. If the Meta was found, the polymorphic query could be done. Traverse
>> the models down from the initial model class (i.e. the one from which the
>> PQ was done on) enumerating concrete and nonproxy models. Basing in your
>> idea, a narrow=(Model1, Model2, ...) argument could be specified to only
>> include those models in the list, ignoring the rest (and stopping when all
>> those model classes were iterated and found). As complement, an
>> exclude=(Model1, Model2) could be alternatively specified to skip those
>> classes (as skipping proxy and abstract classes in the enumeration).
>>
>> 3. Perform a select_related or prefetch_related query with the enumerated
>> classes. This would do a join or prefetch perhaps only on the classes of
>> interest (narrow=/exclude=) instead of doing the biggest possible join.
>>
>> An alternative could be that to define a polymorphic model, the parent
>> model could be a brand new contenttypes.models.PolymorphicModel (itself
>> being abstract=True) and the nearest concrete ancestors must implement such
>> Meta attributes (or an exception should be throw). Perhaps this (abstract)
>> model could have a metaclass defining a new Manager for 'objects' attribute
>> which could generate a queryset implementing this polymorphic() method.
>>
>> Such model could have the widely-mentioned get_real_instance (as in
>> django-polymorphic) or narrow() as mentioned in the post. The
>> implementation could vary: it starts by getting the current object's
>> contenttype from the discriminator and get the model class for it. if
>> narrow-style is implemented, issubclass() could be called to determine
>> whether the object belongs to any of those classes and return the real
>> instance if so (it could avoid loading a non-specified class lazily).
>> implementing get_real_instance class could load lazily the class if was not
>> specified.
>>
>> As I see, an implementation like I described (which is not new at all)
>> could let you leverage the polymorphism level and let you suffer the
>> tradeoffs you choose.
>>
>> Remember that, with this (rant-styled, but improved from reading the post
>> you pointed me to) proposal, anyone could choose to use the polymorphism in
>> the queries or not, by calling explicitly such method on the query. Not
>> using it would behave as normal queries.
>>
>>
>>
>> El jueves, 5 de junio de 2014 20:03:14 UTC-5, Russell Keith-Magee
>> escribió:
>>
>>>
>>> On Fri, Jun 6, 2014 at 6:49 AM, Luis Masuelli 
>>> wrote:
>>>
 What about integrating polymorphic features in the ORM? It's like
 having the features of django-polymorphic but in the core.

 The polymorphism could be acheved by:
 1. Having contenttypes installed (this is a common pattern).
 2. Specifying a root (first ancestor) model class like:

 class MyParentModel(models.Model):
 ...

 class Meta:
 polymorphic = True
 discriminant = "somefield" #it could default to
 'content_type' if not specified. This field could be created.

 To achieve the polymorphism a query could be like:

 objects = MyParentModel.objects.filter(foo=bar,baz=clorch,...).
 polymorphic().more().calls().ifneeded()

 Such method could complain if the contenttypes applica