simple model problem

152 views
Skip to first unread message

arbi

unread,
Mar 4, 2009, 1:43:03 PM3/4/09
to Django users
Hello,
I am new to Django and programming...
I have a model similar to this one :

class myModel :
attribute 1 = models.ForeignKey(myModel2, primary_key = True)
attribute 2 = models.ForeignKey(myModel3, primary_key = True)

is it possible to have two primary keys?
In fact I want that the id of an instance of this class is the
concatenation of the (attribute 1 +attribute2).
How to do this?
thx

Arbi

Malcolm Tredinnick

unread,
Mar 4, 2009, 8:57:37 PM3/4/09
to django...@googlegroups.com
On Wed, 2009-03-04 at 10:43 -0800, arbi wrote:
> Hello,
> I am new to Django and programming...
> I have a model similar to this one :
>
> class myModel :
> attribute 1 = models.ForeignKey(myModel2, primary_key = True)
> attribute 2 = models.ForeignKey(myModel3, primary_key = True)
>
> is it possible to have two primary keys?

No. One primary key per model.

> In fact I want that the id of an instance of this class is the
> concatenation of the (attribute 1 +attribute2).
> How to do this?

You might be able to do it with a custom field type and fair bit of
code. However, this is definitely not the approach to take if you are
just starting out.

Instead, just let the primary key be the default one Django provides you
with. You can have another property or method on the model that creates
your combined value that you can use for other purposes. Trying to
overly control the primary key almost always is not necessary.

What is the problem you are really trying to solve here?

Regards,
Malcolm


AmanKow

unread,
Mar 5, 2009, 1:40:19 PM3/5/09
to Django users
On Mar 4, 8:57 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:
I think that all you require is that you use the standard, automatic
primary key, and ensure that the two fields are indexed and unique
together.

http://docs.djangoproject.com/en/dev/ref/models/options/#unique-together

Wayne

bshaurette

unread,
Apr 24, 2009, 4:21:26 PM4/24/09
to Django users
Is it actually possible to define a primary key that is a
concatenation of two fields?

I'm working on a project to get the admin to work on top of a legacy
db - it's an old db with a few, ahem, design problems. For the most
part I've been able to get around the bad structure with a few simple
model adjustments, but today I came across a table that has just three
cols - and no id:


class Priority(models.Model):
tags = models.ForeignKey(Tags)
content = models.ForeignKey(Content)
rank = models.IntegerField()

class Meta:
db_table = u'priority'
unique_together = (("tags", "content"),)


My preference would be just to add an 'id' column to the table, but
we're trying to keep db changes to a minimum (changing one means
changing the same table in at least a dozen more - not optimal, but it
is what it is). Without it, I'm throwing "Unknown column
'priority.id' in 'field list'" as an error.

Each record needs to be unique on tags + content anyway. Would it be
possible to define a concatenated primary key using these two cols?
What approach would you take? (Or should I just fight a little harder
to make the adjustment to the table itself?)

Malcolm Tredinnick

unread,
Apr 24, 2009, 4:46:28 PM4/24/09
to django...@googlegroups.com

On Fri, 2009-04-24 at 13:21 -0700, bshaurette wrote:
[...]

> My preference would be just to add an 'id' column to the table, but
> we're trying to keep db changes to a minimum (changing one means
> changing the same table in at least a dozen more - not optimal, but it
> is what it is). Without it, I'm throwing "Unknown column
> 'priority.id' in 'field list'" as an error.
>
> Each record needs to be unique on tags + content anyway. Would it be
> possible to define a concatenated primary key using these two cols?
> What approach would you take? (Or should I just fight a little harder
> to make the adjustment to the table itself?)

I'm miles behind on my django-users reading, but saw this floating
past... This isn't necessarily the happy answer, but I think table
adjustments might be the pragmatic approach here unless you have many
days to spend on the problem.

"Faking it" for a primary key column is hard. The reason being that
there is a lot of code internally which access SomeModel._meta.pk and
forces that into the column list or expects it to be present when
processing results.

Now, I said "hard" and not "impossible", because it might be possible to
make this work in a reasonably transparent fashion if you created a
custom field that was the concatenation of two other fields. After all,
that's kind of how GenericRelation fields work. I'd be focusing on how
model instances were created (QuerySet.iterator and get_cached_row() in
django.db.models.query) when testing this out if you were really
motivated to do so.

Multi-column primary keys is something that's been on my list for ages
and the reason it's not done yet is because it's just very fiddly
internally -- so many places to test and modify and assumptions to
identify.

Naturally you could solve your problem "properly" by making the
necessary changes to Django itself and using a modified version, but,
that's why I wrote the previous paragraph: it's certainly possible and
not necessarily that hard (easier than trying to write a fake field that
works with out-of-the-box Django, I would guess), but it would be fairly
fiddly and time consuming.

Regards,
Malcolm

Reply all
Reply to author
Forward
0 new messages