Why is the primary key specified on the relation field, rather than just
being part of MyModel3? A model has a primary key, and the foreign
relation should use that in the natural case. It's not a property of the
relation, it's a property of the target model and should be declared
there.
There might be an argument for a multi-column version of to-field, but a
tuple or list would seem the easiest way of specifying that, rather than
a variable number of arguments.
At that point, I think normal ForeignKey fields could be adjusted to
Just Work(tm), since they'll know they're related to a model with a
multi-column primary key.
Regards,
Malcolm
Generic relations are quite different to foreign keys and the two
shouldn't be merged.
Generic Relations say how to get from an object id and a content type to
a remote object. They aren't a database-layer construct, although a
database constraint to, e.g., the content-type table could be
enforced(but that's not relevant here). ForeignKeys are a representation
of a database constraint, always referring to same remote table. They
are necessarily different concepts and I dont' think attempting to merge
them is going to gain much in clarity. At some point when multi-column
primary keys are supported, we might be able to work out a way for
generic relations to handle them, but I'm not holding my breath about
that and it's certainly a phase 2 or phase 3 thing. The reason it's
almost impossible to support generic relations with arbitrary
multi-column fields because the number of columns is, well, arbitrary
(attempting to jam multiple remote values into one local database column
is a bad idea, too. At some point the hacks mount up beyond the point of
usefulness). That is, one content type requires one value, a different
one requires two and a third content type might require four values to
identify the object. I strongly suspect we'll end up just saying
GenericRelation fields only work for single valued objects ids. Which
isn't at all unreasonable, since Django's generic relation classes
aren't really compulsory for data modelling. Any given situation has a
solution that doesn't involve them.
> Although the more I think about it we'd still want to
> magically handle ForeignKey's so the same problem exists.
There's no magic in programming. :-)
Maybe be you mean transparently. If so, I think this is a requirement,
too, but it's not a problem. We know when the ForeignKey field is
specified which model it refers to, so we can include the correct number
of database columns at table creation time. We have perfect information
when we create the table, which is where this differs from any generic
relations.
> I guess I could write a composite foreign key manager, which could be
> used in both instances. The problem is the API is very confusing at
> the moment, and I haven't been able to work out a good way to handle
> (in the code) mycomposite__exact=1 (single to multiple relation
> lookup). Maybe you could help with this :)
The value on the right hand side can be any sequence or tuple (or even
an object that knows how to return a sequence or tuple). The ORM will
know that the field involved is a multicolumn field and know to expect
multiple values on the RHS to associate with the multiple LHS columns.
It doesn't make sense to say mycomposite__exact=1, since mycomposite
expects multiple values. It's clear what
mycomposite__exact = (1,2)
means, however.
I will finish my work on this when I get a chance and as soon as
possible. I realise you've been waiting for a bit. Haven't had a lot of
time for Django the past few weeks, but I'm getting back on the horse
again now, although there'll be a bit of focus on 1.1 feature triage and
1.0.X for a little bit first.
It doesn't mean that you need to specify the primary key columns on the
ForeignKey field, though. As I pointed out in the original message, you
know which are the primary key columns because they're declared on the
model referred to.
>
> Really, this issue is all thats stopping me from completing the
> composite PKs patch.
You should still have something that's in multiple portions, though.
Relations are kind of a second phase to the rest. So you could open a
ticket with the first part of the patch if you want some early review on
that (although you've missed the 1.1 window now, so it will be
deprioritised a little bit officially, but I'm still interested in
coming to some conclusion on this).
Regards,
Malcolm
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
It needs to be taken into account, but it's certainly solvable and not
an obstacle to success. There are two solutions available:
(1) Postpone creating the first table until we have read the second
table so that we know the number of columns. This isn't too hard,
although it means you end up making two passes over some classes'
internals in some cases. But table creation is such a rare event and the
Python code is so fast that it's easily affordable. We're not talking
about something changing from 15 minutes to 20 minutes or anything.
(2) The poor-man's approach is "ALTER TABLE", which is a small-ish
change, but butt ugly. I prefer the former solution, but the this is the
silly drop-in I've got at the moment just to make things possible to
develop with.
Realise that the reason we have string-ified forwards references is to
avoid the need for circular imports. But at some point we'll end up
importing everything anyway and then we can go and look at the number of
required columns. This is why forwards references work in the first
place -- at a later time we go back and fix up the internal references
to point to the Python objects in question. We can change table creation
to operate similarly. It's not that hard.
Regards,
Malcolm
regards
Steve
[...]
> Sure. Perhaps it's not common terminology: by "recursive" I meant a
> self-referential relationship, though now you mention it I see that the
> same issue can occur if the order of model definitions is sub-optimal.
The recursive case is just a collapsed form of forwards references, so I
didn't address that specifically. You don't even need sub-optimal
ordering to require forwards references. For example, circular reference
loops (particularly with NULL relations) aren't unheard of. Even in
Django, you need forwards reference to implement the "through" option
for ManyToMany fields, since you need to define the intermediate model
with a ForeignKey to model A and then define model A with a many-to-many
through the intermediate model. So one of them has to be defined second.
All I'm saying is that forwards references crop up naturally; they're
not a wart (and references to the same model are the other obvious case
they crop up naturally).
Regards,
Malcolm
@#$%!.....will this composite primary key feature be included in
Django 2.0? Or will this be ever included? Let me explain my
frustration a bit.
Open source, remember? This means that leadership is a bit like herding
cats. I think you just took a good shot at pissing the cats off.
regards
Steve
It's hard for me to figure out how to answer this: if you've got a
problem with my leadership skills, I don't really see how anything I
say makes much of a difference. Frankly, your tone is completely
inappropriate and I feel I'm enforcing absurdly out-of-line behavior
simply by responding.
However, I'm just going to ignore those parts of your post and focus
on the real question.
Support for composite keys has indeed been requested before. In fact,
it's ticket #373; opened about three years ago! On July 20th, 2006, I
commented:
"""
[He]re are the issues [...] that would need to be solved to make this work:
There's three basic problems in dealing with composite primary keys in Django.
The first is that a number of APIs use "obj._meta.pk" to access the
primary key field (for example, to do "pk=whatever" lookups). A
composite PK implementation would need to emulate this in some way to
avoid breaking everything.
Second, a number of things use (content_type_id, object_pk) tuples to
refer to some object -- look at the comment framework, or the admin
log API. Again, a composite PK system would need to somehow not break
this.
Finally, there's the issue of admin URLs; they're of the form
"/app_label/module_name/pk/"; there would need to be a way to map URLs
to objects in the absence of a primary key.
"""
(http://code.djangoproject.com/ticket/373#comment:3)
That's a pretty clear list, and it's been sitting out there for over
two years. I've pointed folks at that comment any number of times
since then, and at some point someone expanded somewhat into a wiki
page (http://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys)
that could serve as a simple spec.
And yet three years on I've yet to see a patch appear on #373. Yes,
this gets asked for time and time again, but nobody seems to want it
enough to write even a *partial* fix. Why should this be?
I think the main reason is that the lack of the feature is quite easy
to work around in most cases. So most people who could fix it just
don't feel like it's worth the time and move on. Somehow, despite the
strum und drang there isn't really enough energy here to prompt anyone
to work up a patch.
Patches are the unit of currency in this community. With very few
exceptions, every one of Django's thousands of commits began life as a
patch posted by someone in the community. We committers can be a lot
more effective when we review and integrate other peoples' patches — I
can review a dozen patches from a dozen different people in the time
it takes me to fix one bug on my own — so by necessity we have to rely
on our community.
If there's a feature you need, implement it. If you can't figure out
where to start, ask — I'm on #django-dev during most of the work week,
and I'd be happy to help anyone who wants to hack on this feature. If
you don't want to or can't implement it yourself, there's a legion of
options available ranging from asking around for help to organizing a
team to contracting someone qualified.
Finally, please keep in mind that the feature list we're drafting
right now isn't set it stone. Anything that gets finished between now
and the feature freeze date for 1.1 (2/15/09) is a candidate for
inclusion. We develop these feature lists to help people figure out
what to work on; nobody's gonna tell anyone not to scratch their own
itch — that's what open source is all about.
Jacob
If you'll share your code — #373 is begging for a patch... — others
can use it as a starting place.
Jacob
Cool; I'll take a look tomorrow. Do you want me to make changes in my
own tree, or would you rather patches back to you?
Jacob
I'm sorry, but you're essentially 100% incorrect about the
maintainership techniques and a large number of your other claims about
the ORM.
The changes required for composite primary keys are relatively
localised. There's more than one place, but there's a limited number of
them. For example, since a lot of the logic is already encapsulated by
having a "pk" property already, it's mostly those places that need
attention.
Similarly, despite your beliefs, all the maintainers have have been
setting directions for this work in the sense of encouraging, guiding
and providing regular detailed feedback, as the most casual regular
observer on this mailing list could see. But it's not code production by
fiat in the open source world. We aren't going to tell people what to
work on, but we do keep an eye on things and also have our own interests
that we push along. For a couple of years, there's been fairly
coordinated and steady activity towards improvement in various areas,
including the ORM. They remain ongoing.
Again, as with Jacob, I've been reluctant to respond to this thread
because you're just so out of line with your criticisms and the ad
hominem attacks are fairly insulting (and since you mentioned me by name
and by implication in your attacks on Jacob, I am definitely going to
take offence at your mischaracterisations). You happen to want composite
primary keys for your particular situation. But in the whole broad
scheme of every possible web application and database usage, they just
aren't the most common use-case in the world, so will happen in due
course when they're done. Yes, they're on the table; have been for quite
a while. Which is why they're always part of the equation in ORM design
work. The latest round of large ORM changes last year used this case as
one influence over quite a lot of the design, contrary to your
observations (and I can speak with some authority to that point).
If this was/is so blindingly important to you, where's your patch? You
are the one with the apparently show stopping need for this and you get
paid at least 10 times as much as me to work on Django (even if you get
paid $0), so if it's so important to your job, put up or shut up. You
are welcome to use Django. We are glad you do. But that doesn't mean you
get to post crap like this when your favorite feature isn't yet
implemented.
> On the other hand, i have to say that I am not too familiar with this
> open source style of working on a project.
Clearly.
> At my company, issues like
> this that span across multiple sub sections usually can only be
> resolved by management stepping in.
One of the reasons why most corporate software is of much lower quality
than Open Source software.
> From what I've read here in the
> user/dev mailing list, it seems that the only reason that this can't
> be resolved is due to lack of leadership from above.
Nonsense. You're mischaracterising the entire situation. It isn't "not
resolved" (whatever definition of "resolved" you happen to want to
choose). It's ongoing work that hasn't been finished yet. The bar for
quality is high and there are other, simultaneous priorities and limited
resources.
> (Totalitarian
> states usually are pretty efficient in execution...military, another
> example...perhaps sqlalchemy could be a third example with MB being
> the strong leader). Anyway, i guess by seeing your email I've already
> achieved quite a bit. Simply having you recognizing such a problem
> again after 2 years i think it's already going somewhere. Perhaps in a
> few days we will see some patches coming in.
Seriously, put down the weed and step away from the keyboard. Have you
followed any of the discussion about this at all?
David, myself and a number of others have been having ongoing
discussions for a few months in the latest round. It's progressing
fairly nicely, given the time we have available and all the other pieces
we're all working on as well. As mentioned above, it's also been one of
the many, many considerations when designing other pieces of the
infrastructure and has been duly waiting in the queue for the
appropriate moment to start making the changes (which is around now).
The reason the ticket has been open is to indicate it's ongoing work and
we haven't been unaware of it. It's just not done yet (see, again,
priorities and lack of a complete patch that meets the quality
standards).
This whole sub-thread has been quite disappointing.
Regards,
Malcolm
Yo. Not that big, but there's a DBA involved for some of 'em. Let's
just say I can't use the auth-system or anything depending on that :)
Funny thing though, got a manytomany-table without a primary key: I
can add a new row easily enough, the only problem is in delete()-ing
specific rows, since that seems to use the primary key. So I clear()
and re-add instead of delete()-ing, since that doesn't use the primary
key. Fragile, but it beats doing the puppy-eyes to the DBA.
HM
Good way to prevent a discussion from entering Godwin-territory :)
I should perhaps have mentioned something along the lines of "this is
an example of where there is (perhaps) an unnecessary need for a
primary key". After all, the fewer places that *must* have x, the
easier it is to change the underlying structure of x.
To go back off track (wouldn't do to stay on it for long), maybe we
need an official place to discuss the use of legacy databases in
Django.
HM
So here we are 4 years later, version 1.5 is about to be released and we still don't have a solution for composite primary keys in the code base? Or am I missing it in the docs somewhere? --
You received this message because you are subscribed to the Google Groups "Django developers" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-developers/-/UnrMyhTujxIJ.
To post to this group, send email to django-d...@googlegroups.com.
To unsubscribe from this group, send email to django-develop...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
--
You received this message because you are subscribed to the Google Groups "Django developers" group.