Code

Opened 5 years ago

Closed 5 years ago

#10010 closed (invalid)

ManyToMany programming error

Reported by: rmaciejczyk@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.0
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I'm rather newbie in the django and python programming, but I'm experienced IT guy.
I tried to define data model matching to existing database (Postgresql)
Below you can find my sample code.

class DBProduct(models.Model):
    name = models.CharField(max_length=128)
    
    class Meta:
        db_table = u'product'

class DBStore(models.Model):
    name = models.CharField(max_length=256)
    sotreproducts = models.ManyToManyField(DBProduct, through='DBStoreProducts')
        
    class Meta:
        db_table = u'singlestore'

class DBStoreProducts(models.Model):
    
    store_conf = models.ForeignKey(DBStore, db_column='store_id', primary_key=True)
    product_id = models.ForeignKey(DBProduct, primary_key=True)
    
    class Meta:
        db_table = u'storeproducts'

When I execute the following code:

    store_config = DBStore.objects.get(id=1)
    values = store_config.products.all()

I get the following Programming Error:

ProgrammingError
column storeproducts.product_id_id does not exist
LINE 1: ...product" INNER JOIN "storeproducts" ON ("product"."id" = "storeproducts...

I suppose it's related to the foreign keys configuration in the DBStoreProducts table,
since for the 'store_conf' field a database column name is defined explicitly (store_id),
but for the product_id field not. What I expected was to use a database field named the
same as 'product_id' field.

To sum up when I've changed the model and set the database column name for product id

    product_id = models.ForeignKey(DBProduct, db_column='product_id' primary_key=True)

everything seems to go smoothly, so that's obviously ManyToMany field bug.

I'm using Django 1.0.2 (stable release), Python 2.6.1 for Windows.

(BTW. All above examples have been written by hand since I needed to change my quite a secret
table names ;) Sorry for spelling mistakes)

Attachments (0)

Change History (8)

comment:1 Changed 5 years ago by ubernostrum

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

I don't see any actual description of a bug here, just the expected behavior for Django when you have a column name that doesn't match the default of the ORM.

comment:2 Changed 5 years ago by rmaciejczyk@…

The bug is that when you define ManyToMany intermediate table with below keys:

   store_conf = models.ForeignKey(DBStore, db_column='store_id', primary_key=True)
    product_id = models.ForeignKey(DBProduct, primary_key=True)

and for one key specify database column name, but for the other not, you get the exception
when you execute the code:

DBStore.objects.get(id=1)
values = store_config.products.all()

ProgrammingError
column storeproducts.product_id_id does not exist
LINE 1: ...product" INNER JOIN "storeproducts" ON ("product"."id" = "storeproducts...

According to the doc you don't have to define database column names for all keys and as a default value
the class field name is used, but in my example if you define the db_name for at least one field you must do it for all the rest. Otherwise the exception will occur.

comment:3 Changed 5 years ago by rmaciejczyk@…

  • Resolution invalid deleted
  • Status changed from closed to reopened

comment:4 Changed 5 years ago by ramiro

The DBStoreProducts model has more than one field with primary_key option set to True. It's strange that the pre-flight validation isn't catching it.

comment:5 follow-up: Changed 5 years ago by rmaciejczyk@…

Yes, it's done intentionally, since both these fields have been set in my database as primary key (they are unique together).

comment:6 in reply to: ↑ 5 ; follow-up: Changed 5 years ago by ramiro

Replying to rmaciejczyk@nglogic.com:

Yes, it's done intentionally, since both these fields have been set in my database as primary key (they are unique together).

But it a unsupported configuration, see http://docs.djangoproject.com/en/dev/ref/models/fields/#primary-key

It seems there isn't a check for this in django/core/management/validation.py.

comment:7 in reply to: ↑ 6 ; follow-up: Changed 5 years ago by anonymous

Replying to ramiro:

Replying to rmaciejczyk@nglogic.com:

Yes, it's done intentionally, since both these fields have been set in my database as primary key (they are unique together).

But it a unsupported configuration, see http://docs.djangoproject.com/en/dev/ref/models/fields/#primary-key

Ok, now I see. Thanks.

But I have the following "join" table in my database (there is no way to make a change in the table);

StoreProducts
-------------
store_id : INTEGER PK
product_id: INTEGER PK
other_field : INTEGER

See, there is no 'id' column and store_id and product_id are both primary key.
(this is a common approach in many databases according to the SQL reference).

Could you tell me how I should define my django model for this table?

comment:8 in reply to: ↑ 7 Changed 5 years ago by ramiro

  • Resolution set to invalid
  • Status changed from reopened to closed

Replying to anonymous:

See, there is no 'id' column and store_id and product_id are both primary key. (this is a common approach in many databases according to the SQL reference).

Could you tell me how I should define my django model for this table?

Given current I'd say it isn't currently possible to describe that that with Django models. At any rate it' material for django-users mailing list, closing this ticket again.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.