简体   繁体   中英

Django query: Joining two models with two fields

I have the following models:

class AcademicRecord(models.Model):
    record_id = models.PositiveIntegerField(unique=True, primary_key=True)
    subjects = models.ManyToManyField(Subject,through='AcademicRecordSubject')
    ...


class AcademicRecordSubject(models.Model):
    academic_record = models.ForeignKey('AcademicRecord')
    subject = models.ForeignKey('Subject')
    language_group = IntegerCharField(max_length=2)
    ...


class SubjectTime(models.Model):
    time_id = models.CharField(max_length=128, unique=True, primary_key=True)
    subject = models.ForeignKey(Subject)
    language_group = IntegerCharField(max_length=2)
    ...


class Subject(models.Model):
    subject_id = models.PositiveIntegerField(unique=True,primary_key=True)
    ...

The academic records have list of subjects each with a language code and the subject times have a subject and language code.

With a given AcademicRecord , how can I get the subject times that matches with the AcademicRecordSubjects that the AcademicRecord has?

This is my approach, but it makes more queries than needed:

# record is the given AcademicRecord
times = []
for record_subject in record.academicrecordsubject_set.all():
    matched_times = SubjectTime.objects.filter(subject=record_subject.subject)
    current_times = matched_times.filter(language_group=record_subject.language_group)
    times.append(current_times)

I want to make the query using django ORM not with raw SQL

SubjectTime language group has to match with Subject 's language group aswell

Given an AcademicRecord instance academic_record , it is either

SubjectTime.objects.filter(subject__academicrecordsubject_set__academic_record=academic_record)

or

SubjectTime.objects.filter(subject__academicrecordsubject__academic_record=academic_record)

The results reflect all the rows of the join that these ORM queries become in SQL. To avoid duplicates, just use distinct() .

Now this would be much easier, if I had a django shell to test in :)

I got it, in part thanks to @Robert Jørgensgaard Eng

My problem was how to do the inner join using more than 1 field, in which the F object came on handly.
The correct query is:

SubjectTime.objects.filter(subject__academicrecordsubject__academic_record=record,
                           subject__academicrecordsubject__language_group=F('language_group'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM