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

Question:

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?

Asked By: BillTheKid

||

Answers:

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.

Answered By: Manoj Tolagekar

=========== 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

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

Answered By: Hunain Raza
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.