Re: I would like to discuss my proposal for a working way to call .add() on an m2m with through= model

2017-04-17 Thread Luis Masuelli
I'm quite happy to see the topic is at least being considered! <3.

Although I suggested a solution, I like the solution posted by Collin in 
the PR (I'd prefer solutions not involving signature changes in methods, 
but anyway those signature changes Colin posted are not so... obtrusive).

I'd like to, however, propose a little change in Collin's code. Immediately 
before this code in _add_items:

self.through(**dict(through_defaults, **{
'%s_id' % source_field_name: 
self.related_val[0],
'%s_id' % target_field_name: obj_id,
}))

This one:

if callable(through_defaults):
through_defaults = 
through_defaults(self.related_val[0], obj_id)

With these two lines, we could allow passing a callable to through_fields 
(as we pass callables for defaults in django fields). The return value of 
such callable should be a dictionary, while the arguments should be source 
and target ids.

But even if this little change is not implemented, I like the Collin's 
solution anyway.

Another subtopic to discuss is about enhancing the Collin's solution, is to 
allow through_defaults be specified on field definition (In the same way we 
define default values in... scalar... fields; I leave open the discussion 
on whether such value should be overriden when using add, create, or any of 
these methods as changed by Collin).

I like how this is going and hope that any solution (even if it is just the 
as-is solution provided by Collin, with no changes) be accepted in any 
near-future version <3.

El martes, 21 de marzo de 2017, 20:29:33 (UTC-5), Alex Hill escribió:
>
> Here's a little bit more historical discussion on the topic: 
> *https://groups.google.com/d/topic/django-developers/uWe31AjzZX0/discussion 
> *
>
> On Wed, 22 Mar 2017 at 05:57 Russell Keith-Magee  > wrote:
>
>> On Tue, Mar 21, 2017 at 2:37 PM, Adam Johnson > > wrote:
>>
>>> It does seem like a somewhat arbitrary historical restriction. Collin's 
>>> PoC change is surprisingly small and simple.
>>>
>>> Seems like it would be fine if Django allowed add() and let any errors 
 about missing data bubble-up.

>>>  
>> As the person who *made* the “somewhat arbitrary historical restriction”… 
>> :-)
>>
>> Honestly - the reason it was made was scope creep. 
>>
>> I was trying to land Eric’s work on #6095, which was already moderately 
>> complex. Nobody disagreed that adding an object to an m2m with a through 
>> model was a *bad* idea - there were just a few design decisions that had to 
>> be made. But if we made those decisions, #6095 was going to take *another* 
>> couple of months to land; the perfect being the enemy of the good, we 
>> decided to limit scope and land “simple” m2m add, and revisit the issue 
>> later.
>>
>> I guess now is “later”… :-)
>>
>> Yours,
>> Russ Magee %-)
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Django developers (Contributions to Django itself)" 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 https://groups.google.com/group/django-developers.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/django-developers/CAJxq849m632K%3DaMfXGBtF%3DhMXFS9ujzU6xfUzNxSRkkN_UrkqQ%40mail.gmail.com
>>  
>> 
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" 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 https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a32cf6ae-324a-40c1-b9d9-31bd43af2c2c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


I would like to discuss my proposal for a working way to call .add() on an m2m with through= model

2017-03-20 Thread Luis Masuelli
I was reading this link in the official history 
 and this other link 
in this group 
, 
but still do not understand why the issue against a way to call .add() to 
add a through model. I thought several approaches (they are all backward 
compatible for the end-user) that could work:

   1. Avoid the restriction to call add() if the model has only the two FK 
   fields.
   2. An additional way to call .add() specifying additional fields to fill 
   (this one is not mine; was discussed in the linked thread). You risk 
   getting a (wrapped?) exception if you do not populate other fields 
   appropriately.
   3. (This one was the first I thought and perhaps the easiest to 
   implement) Allow the ManyToManyField to specify a kwarg like 
   `through_factory=` which expects a callable which would populate more data. 
   The restriction to call .add() would remain if no `through_factory=` is 
   specified.
   4. Avoid the restriction to call delete() if the model has only the two 
   FK fields. 
   
I considered these cases:

   - It is quite trivial a model with only two fields, but perhaps the 
   intermediate models could have additional useful methods. I see no trouble 
   having such model and allowing .add() or .delete() calls there.
   - Having a special factory method would allow calls to .add() since we'd 
   be providing a way to make .add() actually know how to create an instance 
   of the intermediate model.
   - You can combine these points, implement one, none, or all of them.
   - (I did not consider extended use cases for delete() intentionally, 
   since perhaps a strange model (with different field pairs) could fit in 
   different relationships, although I cannot think in a case with multiple 
   relationships not incurrin in, perhaps, duplicate data when tried to be 
   used as through= model, but anyway I prefer to keep silence for other cases 
   involving delete(), but the case I stated).
   - It is up to the user to be careful regarding migrating an intermediate 
   model regarding adding, changing, or deleting fields. But anyway, this 
   applies to any modification in the database models right now.
   - Points 1, 2, 3 and/or 4 could be implemented with no clash. A combined 
   approach of 1, 2, 3 would look like this (this flow only applies for the 
   case when the through= is present - such scenario right now only consists 
   of raising an exception; the case with no through= model would not be 
   affected at all):
  - Instantiate `instance = ThroughModel(fka=a, fkb=b, 
  **kwargs_from_add)` with the respective model instances a and b, from 
  classes A and B which hold the desired M2M relationship. In this case, 
the 
  point 2 just adds the **kwargs_from_add. If point 2 is not implemented, 
no 
  **kwargs_from_add would be present.
  - (*If point 3 is implemented*) Call the callable in 
  `through_factory=` invoking it `like_this(instance)`, if the callable is 
  present. It is expected to save the instance.
  - (*If either point 1 is implemented and the model has only two 
  fields, or point 2 is implemented*) Manually save the instance (if 
  point 3 was not implemented or it was but the factory callable was not 
  specified). (*Otherwise - point 2 not implemented AND (point 1 not 
  implemented or model with more than two fields*)) Raise the currently 
  implemented exception for the .add() method with through= specified (with 
a 
  different string message) because the through_factory was not present, 
and 
  so the framework does not know how to populate additional fields.
  - Catch-and-reraise (or don't catch at all and let them be) the error 
  for missing data in the tried-to-save model.
   - An example of the callable in point 3 would be like this (just an 
   example for, say, a game!):
  - def on_added(through_model_instance):
  through_model_instance.balance = 1000.0 #although this one could 
  be a default value at db level.
  through_model_instance.save()
  through_model_instance.achievements.create(tag=
  'joined-this-relation')
  
I understand these approaches, combined or not, could not be perfect or 
bug-free. But I'd like to discuss them instead of plainly discard them. 
AFAIK right now the calls to .add() are disallowed when through is 
specified.

Could we work or at least discuss these use cases now? The history I quoted 
seems to be pretty historic, and we're in 2017. The first thing I'd 
like to know right not (with django 1.10 alive) is the feasability of this 
feature in a future django version.

I await your comments and/or criticism ^^.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop 

Make ManyToMany fields support "to_field".

2016-01-12 Thread Luis Masuelli
Currently, if I want to create a ManyToMany relationship, I'm stuck with 
two options:


   - Accept the by-default configuration. This will imply the inner table 
   will have two fields based on the respective PKs.
   - Create a through-model. I will be able to specify two foreign keys, 
   one for each table. I will lose the ability to cal .add and .delete.

Is there a chance to let the user specify custom to_field (and say, 
"from_field") in a M2M field? I think it would be a nice feature, as we 
already allow them in FK and O2O fields.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" 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 https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ad91bad2-83a8-4884-a47e-34dc59646b67%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Is there a reason these features cannot be added inside Django core?

2016-01-12 Thread Luis Masuelli
These features are pretty core-related.

1. Features from django-polymorphic. To mantain bw compatibility, the 
hierarchy parent could need to add something like polymorphic=True in the 
meta to this feature be activated.
2. Something like this snippet regarding Inlines in 
admin: https://djangosnippets.org/snippets/2032/, to be able to do this:

class A(models.Model):

b = OneToOneField('B')

class B(models.Model):

...

class AInlineAdmin(StackedInline):

model = A

class BAdmin(ModelAdmin):

inlines = (AInlineAdmin)

site.register(B, BAdmin)

Sometimes, doing this could be desirable as it was in my case.

Additionally, I don't know if it is a feature or a bug, but when I see the 
inline model section for a O2O field, the section is labeled as:

(verbose_name_plural)
(verbose_name) #1

Example (the Customer model admin has an inline to ContactDetails; the 
ContactDetails model has a direct O2O field to Customer; in this case I 
didn't use the reverse inline snippet I posted above, but the standard 
supported way):

Contacts Details
Contact Details #1

Even when there is only one element (since it is a O2O). Could a change be 
done for that case so these captions become...

(verbose_name)
(nothing)

only for the O2O case? (both in the standard way and -if you decide to 
support- the inverse inline)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" 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 https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a96740fe-c094-401b-82de-891836b6fc8d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Websockets... again

2014-10-28 Thread Luis Masuelli
Is there any current development involving including websockets in django 
core?

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" 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/50768d16-1d05-489c-8cbf-2091d95ff388%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Is this a bug?

2014-09-04 Thread Luis Masuelli
I'm opening a django console (to narrow the problem) and run this line:

for sesion in 
SesionJuego.objects.filter(preguntas__respuesta__isnull=True): print 
sesion, sesion.pk

Where:

* printing is just a sample operation. I'm getting the same error (I'll 
describe later) with any loop body.
* SesionJuego is a custom model class, having a `preguntas` attribute 
which is the reverse side (related_name) of a ForeignKey.
* I have this issue in an atomic view, but I can also reproduce this 
error in console.

I have 1 SesionJuego element, with 5 (related) questions in the database.

What I expect is that such loop iterates over ONE element, ONCE. What I get 
is this (see the console below):


So if I iterate I'm getting a non-unique iteration and the second-to-fifth 
iterations will yield objects without the related `preguntas` (i.e. for 
those objects, the populated `preguntas` has a `count` of 0).

Is this a bug? Seems it is iterating over the join instead of over the 
objects. How can I work in a django-way to avoid that?

-- 
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/42c4415c-2af2-4279-b005-45383e66a7f1%40googlegroups.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 <luisfm...@gmail.com 
> > 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 
>

Integrating polymorphic queries in the framework

2014-06-05 Thread Luis Masuelli
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.

-- 
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/56023d31-de23-4d0a-92d4-be78d8149089%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.