Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM SELECT with join

ERR

Models in django:

class Key(models.Model):
    id     = models.AutoField(primary_key=True, blank=True)
    name   = models.CharField(max_length=50)


class Record(models.Model):
    id         = models.AutoField(primary_key=True, blank=True)
    project_id = models.IntegerField()
    name       = models.CharField(max_length=50)


class Value(models.Model):
    id        = models.AutoField(primary_key=True, blank=True)
    record    = models.ForeignKey(Record)
    key       = models.ForeignKey(Key)
    value     = models.CharField(max_length=255)

I need to select from DB this data:

NAME (from record)
and fields related with this record
[NAME (from key), VALUE (from value)]
[NAME (from key), VALUE (from value)]
[...]

May I use django ORM to make this selection? (for example in SQL select looks like this)

SELECT
    `keeper_record`.`id` AS `record_id`,
    `keeper_record`.`name` AS `name`,
    `keeper_record`.`desc` AS `desc`,
    `keeper_key`.`name` AS `key_name`,
    `keeper_key`.`desc` AS `key_desc`,
    `keeper_value`.`value` AS `value_value`
FROM `keeper_record`
JOIN `keeper_value` ON `keeper_record`.`id` = `keeper_value`.`record_id`
JOIN `keeper_key` ON `keeper_key`.`id` = `keeper_value`.`key_id`
WHERE record_id = id
like image 321
Deadly Avatar asked Oct 26 '11 18:10

Deadly


People also ask

How do I join a query in Django ORM?

Join Queries Join can be done with select_related method: Django defines this function as Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query.

What is the difference between select related and prefetch related?

select_related() “follows” foreign-key relationships, selecting additional related-object data when it executes its query. prefetch_related() does a separate lookup for each relationship and does the “joining” in Python.

How do I merge two QuerySets in Django?

You can also use the chain() method from the Itertools module, which allows you to combine two or more QuerySets from different models through concatenation. Alternatively, you can use union() to combine two or more QuerySets from different models, passing all=TRUE if you want to allow duplicates.


2 Answers

The following selects the values related to particular record id. You can then follow the foreign keys to get the related record and key. Using select_related minimises database lookups.

# Select all values related to a record in your view
record = Record.objects.get(pk=record_id)
values = Value.objects.filter(record=record).select_related()

# In your template
{% for value in values %}
{{ value.record.name }} - {{ value.key.name }} - {{ value.value }}
{% endfor %}

Selecting more that one record

In your sql, you had WHERE record_id = 1, so I showed how to get all the values for a particular record. You could also select the values for more that one record in one query.

# filter all records which belong to the project with `project_id=1`
records = Record.objects.filter(project_id=1)
# select all values that belong to these records
values = Value.objects.filter(record__in=records).select_related().order_by('record')
like image 122
Alasdair Avatar answered Oct 08 '22 19:10

Alasdair


Should be relatively straightforward, since you already have the foreign keys tied together.

Record.objects.select_related().filter(id = variable_that_stores_id)

You can combine that with only to limit the fields that you want to bring back.

like image 44
Jordan Avatar answered Oct 08 '22 21:10

Jordan