8

I develop a certain application, which I found with the specified database and model schema. I am using Django version 1.8.2. Below is presented a problem. Unnecessary fields have been omitted, model names are invented for the purposes of an example, because I can not disclose. Consider the following models A and B.

class B (models.Model):

      name = models.CharField(max_length=100)

class A (models.Model):

      name = models.CharField(max_length=100, primary_key=True)
      related_name = models.ForeignKey(B, null=True, blank=True)

After a long time a project the possibility that there may be several of the same name A, but with different foreign key B. In this particular case, I would like to model the primary key "A" consisted of two fields: name and related name. How to create such a key consists of two fields in django?

sweet_sugar
  • 1,390
  • 3
  • 13
  • 22
  • Is it possible to change the primary key of `A` to be the django default `id` instead? That seems like the obvious fix. – Håken Lid Jul 09 '15 at 18:13
  • Hi :-) Thanks for your reply. This is a good solution, but in my case many tables have as a foreign key table "A" and change to the default id would be a really big effort . Moreover, a lot of code using queries like ' A.objects.get ( pk = "something ")' and change the type of primary key requires a lot of work. For this reason, I am looking for a solution that does not change the key type . The base has a lot of years. – sweet_sugar Jul 09 '15 at 19:08
  • Ok. In that case I don't think this can be solved in django. Django requires a single, unique primary key for each instance. Even if you could use a composite primary key, I'm not sure if it's a good idea when one of the fields in the pk is a nullable foreign key. – Håken Lid Jul 09 '15 at 19:33
  • 1
    Could you use a `ManyToMany` relation instead of a foreign key? It kinda sounds like that is what you need in this case, anyway. – Håken Lid Jul 09 '15 at 19:38
  • I thought about it , but the model "A" has additional fields that may also vary depending on the foreign key "B". As for this case, I have to be sure. Thank you :-) – sweet_sugar Jul 09 '15 at 19:43
  • possible duplicate of [make primary key with 2 fields in Django?](http://stackoverflow.com/questions/4871966/make-primary-key-with-2-fields-in-django) – Louis Aug 28 '15 at 23:00

2 Answers2

6

You want to use a composite key. Django does not support this See here. There is some support but you can't have relationships so it's pretty limited as far as practical usage.

Currently Django models only support a single column in this set, denying many designs where the natural primary key of a table is multiple columns. Django currently can't work with these schemas; they must instead introduce a redundant single-column key (a “surrogate” key), forcing applications to make arbitrary and otherwise-unnecessary choices about which key to use for the table in any given instance.

mikeb
  • 10,578
  • 7
  • 62
  • 120
5

Django does not support composite keys. But you could use unique-together

unique_together = ("name", "related_name")
Gocht
  • 9,924
  • 3
  • 42
  • 81
  • When I would use unique_together, assuming that the models will look as presented in the question. Following the addition of the meta-class model A unique_together = ("name", "related_name"), I could have two lines of name = "Kriss" different field related name? What I mean is that the name field primary_key parameter is set to true. – sweet_sugar Jul 09 '15 at 18:16
  • >>> s = B.objects.create(name="JAN") >>> s.save() >>> d = A.objects.create(name="Stasze") >>> d.save() >>> k = A.objects.create(name="Stasze", related_name=s) return Database.Cursor.execute(self, query, params) django.db.utils.IntegrityError: UNIQUE constraint failed: test_comp_a.name – sweet_sugar Jul 09 '15 at 18:27
  • *It is not a composite PK*, remember that. You are using `name` attribute in `A` class as PK and creating a repeated object. If you will have the same `name` in many `A` objects, don't use it as PK, use an `autoincrement` as default and the `unique_together` will do the trick. – Gocht Jul 09 '15 at 19:01
  • Thanks for your reply. In my case, this does not apply, because due to numerous dependencies to the model A, changes to primary key are not so easy. Thanks to you, I met a new possibility django, which in the future will certainly will use. In this case, it is not a solution for me. Thank you :-) – sweet_sugar Jul 09 '15 at 19:14