BillTheKid
BillTheKid

Reputation: 447

How to make more than one fields primary key and remove auto generated id in django models

Suppose in a relational database schema we have a student, a subject and a teacher which connect to each other with a relation teaches. Also, the relation has an attribute time that stores the time of the lesson. This is the most complete yet simplified example I can think to describe my case. Now, the most pythonic and django-wise way I can think of trying to reach a correct solution is, after creating a model class for student, subject and teacher, to create a new class Teaches, which has the foreign keys for the three other classes; also it has the property date field for time. This class would look something like this:

class Teaches(models.Model):
    teachers = models.ForeignKey(Teacher, on_delete_models.CASCADE)
    subjects = models.ForeignKey(Subject, on_delete_models.CASCADE)
    students = models.ForeignKey(Student, on_delete_models.CASCADE)
    time = models.DateField

    class Meta:
        constraints = [
            fields=['teachers', 'subjects', 'students']
            name='teacher_subject_student_triplet'
        ]

I added the Meta class because this is what this answer recommends as the correct approach.

The problem is that that in the migrations file I can still see the id field. The only way I've seen there is to remove it is to set another field as Primary Key, but in my case I cannot do that, having more than one keys. Any suggestions?

Upvotes: 0

Views: 640

Answers (3)

Hunain Raza
Hunain Raza

Reputation: 1

In settings.py:

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Controls the automatic generation of primary keys of each model if defined in settings.

Read this article: Set AutoField or BigAutoField on a per model basis

Upvotes: 0

Mahammadhusain kadiwala
Mahammadhusain kadiwala

Reputation: 3625

=========== model.py =============

from django.db import models

class TeacherModel(models.Model):
    teacher_code = models.CharField(max_length=255)

    def __str__(self):
        return self.teacher_code

class SubjectModel(models.Model):
    subject_code = models.CharField(max_length=255)
    
    def __str__(self):
        return self.subject_code
    
class StudentModel(models.Model):
    student_code = models.CharField(max_length=255)

    def __str__(self):
        return self.student_code
    

class Teaches(models.Model):
    custom_primary_key = models.SlugField(primary_key=True,blank=True)
    teacher = models.ForeignKey(TeacherModel, on_delete=models.CASCADE)
    subject = models.ForeignKey(SubjectModel, on_delete=models.CASCADE)
    student = models.ForeignKey(StudentModel, on_delete=models.CASCADE)
    time = models.DateField

    
    @property
    def make_key(self):
        new_key = str(self.teacher.teacher_code + self.subject.subject_code + self.student.student_code)
        return new_key

    def save(self, *args, **kwargs):
        self.custom_primary_key = self.make_key
        super(Teaches, self).save(*args, **kwargs)

========= Output ==============

enter image description here

Upvotes: 1

Manoj Tolagekar
Manoj Tolagekar

Reputation: 1970

You can remove autogenerated id by adding primary_key=True, see below code:

 class Person(models.Model):
      username = CharField(primary_key=True, max_length=100)
      first_name = CharField(null=True, blank=True, max_length=100)

setting a field to primary_key=True automatically makes it unique and not null.

Upvotes: 0

Related Questions