Django - create dictionary of associated objects

Django - create dictionary of associated objects



I'm attempting to build a query which will return a list of all technologies and the score of each user associated with each technology. This is based on the following models:


class Technology(models.Model):
technology = models.CharField(max_length=64)

class Result(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
technology = models.ForeignKey(technology, on_delete=models.CASCADE)
skill_level = models.ForeignKey(skill, to_field='level', on_delete=models.CASCADE)

class Skill(models.Model):
level = models.IntegerField(unique=True)



Essentially I'd like to see somthing similar to the following:



{technology: Cisco, users: Alex: skill_level: 1, James: skill_level: 2



I'm not sure whether this can be acheived with a simple query or whether custom joins will need to be done?



I'm also not sure whether I should be building this on the Technology model or the Result model?


Technology


Result






How is the Skill object connected to a User object? for example select * from user where skill_level>2?

– jmunsch
Sep 16 '18 at 0:37


Skill


User


select * from user where skill_level>2






@jmunsch Hey - Thanks for the reply. It's connected only via the Result model currently as the result holds each users skill level against each technology? Does the question make sense with what I'm attempting to achieve?

– Alexander Way
Sep 16 '18 at 0:50






@jmunsch I should be able to acheive what I'm looking to acheive using a queryset on the result model. However, within the template the code would be extremely unmanageable. If I'm able to create the dataset as I'd like then it would be two simple for loops. I've also added an image here to try and explain what I'm trying to acheive (Warning: Created in MS Paint): i.imgur.com/s14snwZ.png

– Alexander Way
Sep 16 '18 at 0:56






So like Result.objects.filter(technology__exact='Cisco').filter(skill__gte=1)?

– jmunsch
Sep 16 '18 at 1:00


Result.objects.filter(technology__exact='Cisco').filter(skill__gte=1)






@jmunsch Kind of, I'd like to see a list of all technologies (Not just Cisco) and all skill levels. However, I'd like to create an array of all users scores for each technology?

– Alexander Way
Sep 16 '18 at 1:02




1 Answer
1



maybe something similar to this (see towards the bottom of the tests.py file):



folder layout



models.py:


from django.db import models

class User(models.Model):
name = models.CharField(max_length=64)

class Technology(models.Model):
technology = models.CharField(max_length=64)

class Skill(models.Model):
level = models.IntegerField(unique=True)

class Result(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
technology = models.ForeignKey(Technology, on_delete=models.CASCADE)
skill_level = models.ForeignKey(Skill, to_field='level', on_delete=models.CASCADE)



tests.py:


from django.test import TestCase
from .models import Result, Technology, User, Skill
from django.forms.models import model_to_dict

class SimpleTest(TestCase):
def test_join(self):
u =
s =
for x in range(0,2):
_u = User(name='User'.format(str(x)))
_s = Skill(level=x)
_u.save()
_s.save()
u.append(_u)
s.append(_s)
t =
for x in range(0, 4):
_t = Technology(technology='blah'.format(str(x)))
_t.save()
t.append(_t)
for x in range(0, 8):
r = Result(user=u[x%2], technology=t[x%4], skill_level=s[x%2])
r.save()

x = Technology.objects.select_related()
print(x.query)
for item in x:
print(item.result_set.values())
print(item.result_set.all().query)
for ok in item.result_set.all():
print(model_to_dict(ok))



test output:


➜ mysite python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
SELECT "mysite_technology"."id", "mysite_technology"."technology" FROM "mysite_technology"
<QuerySet ['id': 1, 'user_id': 1, 'technology_id': 1, 'skill_level_id': 0, 'id': 5, 'user_id': 1, 'technology_id': 1, 'skill_level_id': 0]>
SELECT "mysite_result"."id", "mysite_result"."user_id", "mysite_result"."technology_id", "mysite_result"."skill_level_id" FROM "mysite_result" WHERE "mysite_result"."technology_id" = 1
'id': 1, 'user': 1, 'technology': 1, 'skill_level': 0
'id': 5, 'user': 1, 'technology': 1, 'skill_level': 0
<QuerySet ['id': 2, 'user_id': 2, 'technology_id': 2, 'skill_level_id': 1, 'id': 6, 'user_id': 2, 'technology_id': 2, 'skill_level_id': 1]>
SELECT "mysite_result"."id", "mysite_result"."user_id", "mysite_result"."technology_id", "mysite_result"."skill_level_id" FROM "mysite_result" WHERE "mysite_result"."technology_id" = 2
'id': 2, 'user': 2, 'technology': 2, 'skill_level': 1
'id': 6, 'user': 2, 'technology': 2, 'skill_level': 1
<QuerySet ['id': 3, 'user_id': 1, 'technology_id': 3, 'skill_level_id': 0, 'id': 7, 'user_id': 1, 'technology_id': 3, 'skill_level_id': 0]>
SELECT "mysite_result"."id", "mysite_result"."user_id", "mysite_result"."technology_id", "mysite_result"."skill_level_id" FROM "mysite_result" WHERE "mysite_result"."technology_id" = 3
'id': 3, 'user': 1, 'technology': 3, 'skill_level': 0
'id': 7, 'user': 1, 'technology': 3, 'skill_level': 0
<QuerySet ['id': 4, 'user_id': 2, 'technology_id': 4, 'skill_level_id': 1, 'id': 8, 'user_id': 2, 'technology_id': 4, 'skill_level_id': 1]>
SELECT "mysite_result"."id", "mysite_result"."user_id", "mysite_result"."technology_id", "mysite_result"."skill_level_id" FROM "mysite_result" WHERE "mysite_result"."technology_id" = 4
'id': 4, 'user': 2, 'technology': 4, 'skill_level': 1
'id': 8, 'user': 2, 'technology': 4, 'skill_level': 1
.
----------------------------------------------------------------------
Ran 1 test in 0.011s

OK
Destroying test database for alias 'default'...



related:






Thank you so much! Technology.objects.select_related() is exactly what I needed. I think my issue previously was that I was attempting to use .values() and filter() which was extending the list of technologies. I've been pulling hair out for the past ~8 hours trying to get this to work simply and efficiently

– Alexander Way
Sep 16 '18 at 4:36







The only issue I have now is that if you use a filter such as Technology.objects.select_related().filter(result__user__is_active=True) then it returns a list that's N times as long as the many of users? Not sure how I can filter the data now?

– Alexander Way
Sep 16 '18 at 5:03



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)