* status: new => closed
* ui_ux: => 0
* resolution: => needsinfo
* easy: => 0
Comment:
Discussion with Jacob: closing as needsinfo, the modeling in the ticket
does not seem like it *should* work, a model cannot be an instance of
multiple subclasses.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:12>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: closed => reopened
* resolution: needsinfo =>
Comment:
Here's a more reasonable example...
{{{
# models.py
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
place = models.OneToOneField(Place, parent_link=True,
related_name='restaurant')
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
}}}
Now, say we have a bunch of Place objects in the database, and a form
where users can inform us what sort of business a particular Place is (OK,
this is a contrived example, but I'm sure you can see that this could be a
reasonable use case for some types of data).
{{{
# somewhere in views.py
p = Place.objects.get(pk=1)
restaurant = Restaurant(**{
'place': p,
'serves_hot_dogs': False,
'serves_pizza': True,
})
restaurant.save()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:13>
* status: reopened => closed
* resolution: => wontfix
Comment:
If multiple related objects are linked to the same object, they should
have a foreign key to this object, not "extend" it; that would break the
"instance" paradigm.
You can always use a Python mixin if you have related objects of different
types, but want to share some methods.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:14>
* status: closed => reopened
* resolution: wontfix =>
Comment:
Please see my example immediately above. This is not about foreign keys
or multiple related objects linked to the same object. It's about multi-
table inheritance where the child data isn't always known at the time the
parent object is created.
If you have a Place object that is not yet a Restaurant object, the ORM
will not allow you to add the data to make it a Restaurant object.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:15>
* status: reopened => closed
* resolution: => worksforme
Comment:
Ah, I understand. This works:
{{{
p = Place.objects.get(pk=1)
restaurant = Restaurant(place_ptr=p, ...)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:16>
* status: closed => reopened
* resolution: worksforme =>
Comment:
This leads to the behavior described in #11618 - the parent instance
fields get overwritten.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:17>
* cc: anssi.kaariainen@… (added)
Comment:
If you want to extend an existing instance, you need to copy all fields of
the parent to the new child manually. Unfortunately this can't be done in
a generic way using only public APIs. Although ._meta is semi-public and
doing
{{{
child = ChildModel(**childfields) # set child field values
for field in parent._meta.fields:
setattr(child, field.attname, getattr(parent, field.attname)) # set
child values from parent
child.parent_ptr = parent.pk # not sure if this is strictly necessary,
probably so...
}}}
or something along those lines should work (not tested). Now, I don't
think this can be officially documented without making ._meta.fields part
of the public API. I would have use for a helper method that does this.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:18>
* cc: mike@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:19>
Comment (by Edward Askew <gnutrino@…>):
There's actually an easier workaround for this:
{{{
parent = Place.objects.get(...)
child = Restaurant(place_ptr=parent,...)
#Overwrites the parents fields except the primary key with None (because
the parent fields in child are not auto filled)
child.save()
#Restores the parent fields to their previous values
parent.save()
#hit the database again to fill the proper values for the inherited fields
child = Restaurant.objects.get(pk=parent.pk)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:20>
Comment (by sammiestoel@…):
There is an even easier work around not 100% sure if it works as expected
yet though:
{{{
child = Restaurant(place_ptr_id=place.pk)
child.__dict__.update(place.__dict__)
child.save()
}}}
Tested it myself for my use case as working.
Thanks to: http://stackoverflow.com/questions/4064808/django-model-
inheritance-create-sub-instance-of-existing-instance-downcast
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:21>
Comment (by loic84):
I'm not sure it covers all bases but I use:
{{{
child = Restaurant(place_ptr=place)
child.save_base(raw=True)
}}}
It would be great to have an obvious and officially blessed way of doing
this though.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:22>
* stage: Design decision needed => Accepted
Comment:
I think this makes sense. Unlink child but keep the parent and link child
to existing parent would both be useful in some situatios.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:24>
* status: new => assigned
* owner: nobody => elektrrrus
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:25>
Comment (by aaugustin):
#21537 was a duplicate.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:26>
Comment (by pcompassion):
I'd like this to be implemented as well. I have the following model
relationships and it's just hard to do what django expects me to do when
creating objects.
Thread has 1 main post.
Thread has many other posts
Post has 0-1 parent post.
There are multiple type of Threads.
It's just easier to work with when I can create BaseThread and extend it.
Besides, there are cases where I need to switch Thread types.
If it's possible to treat the base and extended separately, I can keep the
base part, and create the extension part, and connect them.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:27>
Comment (by Reza Mohammadi <reza@…>):
`raw=True` doesn't always work. `raw` is used for two different purposes:
The 'raw' argument is telling save_base not to save any parent models
and
not to do any changes to the values before save. This is used by fixture
loading.
For the purpose of this ticket, we want save_base ignore the first part
but we need the second part to be done.
I think `raw` argument should be split to two different arguments, as its
functionality is already separated. Not as a workaround for this bug, but
to make the code more readable.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:28>
* cc: reza@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:29>
Comment (by juan64645@…):
Hello! I am new in django. I have a problem like this.
I want to do something like this(in inheritance multi-table):
in view.py
restaurant = Restaurant(place_ptr=place)
restaurant.save()
assuming that the attributes of restaurant hold null=True.
but Restaurant(place_ptr=place) returns nothing.
My vercion of django is 1.5
They say about this? Is there any alternative?
That is not to create a new restaurant and it was clear the place, because
it is very ugly.
From already thank you very much!
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:30>
* cc: cmawebsite@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:31>
* cc: ar45 (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:32>
Comment (by ar45):
Anything wrong with [1] this implementation? (taken from Tom Tobin's
branch referenced in this ticket)
[1]
https://github.com/django/django/compare/master...ar45:child_object_from_parent_model
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:33>
Comment (by timgraham):
It's a bit difficult to review without tests. To get a review of the API
design, it's a good idea to offer a high level overview on the
DevelopersMailingList.
--
Ticket URL: <https://code.djangoproject.com/ticket/7623#comment:34>