Mattia Carolo
Mattia Carolo

Reputation: 153

Django models many to many relations

I'm moving my first steps with django and I'm trying to figure out a thing. Suppose that we have a model.py made like this where NameEffect has a many to many relation

class Name(models.Model):
    nameid = models.IntegerField()
    name = models.CharField(max_length=255)

class Effect(models.Model):
    effectid = models.IntegerField()
    effect = models.TextField()

class NameEffect(models.Model):
    nameid = models.IntegerField()
    effectid = models.IntegerField()
    start = models.PositiveIntegerField()
    strand = models.PositiveIntegerField()

and I want to create a QuerySet where every entry contains name,effect,start,strand of the researched name. Fact is that the only solution I found was using raw SQL queries but I can't understand how to do it with the django models approach

Upvotes: 0

Views: 34

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599628

You haven't defined any relationships here at all. You should identify the fields as ForeignKeys - and also define the implicit many-to-many relationship explicitly (although you don't actually need it for this particular query, but it'll definitely come in useful).

class Name(models.Model):
    nameid = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255)
    effects = models.ManyToManyField('Effect', through='NameEffect')

class Effect(models.Model):
    effectid = models.IntegerField(primary_key=True)
    effect = models.TextField()

class NameEffect(models.Model):
    name = models.ForeignKey('Name', db_column='nameid')
    effect = models.ForeignKey('Effect', db_column='effectid')
    start = models.PositiveIntegerField()
    strand = models.PositiveIntegerField()

Now you can can query NameEffect directly to get the result you want.

data = NameEffect.objects.values('name__name', 'effect__effect', 'start', 'strand')

Also note, unless you know you really need just these fields, you should avoid using values and just query NameEffect using select_related:

name_effects = NameEffect.objects.select_related('name', 'effect')

and then access the values when you need them, eg in a template:

{% for obj in name_effects %}
    {{ obj.name.name }}
    {{ obj.effect.effect }}
    {{ obj.start }}
    {{ obj.strand }}
{% endif %}

Upvotes: 0

Related Questions