P200p
P200p

Reputation: 29

How to query the following use case in Django?

I have made a game similar to the drinking game piccolo where you have a list of challenges. Each challenges has variables that need to be filled in (e.g: Player X gives four sips to Player Y). Besides that, a challenge consists of rounds, with each round having an index and a description (e.g Round 0: X and Y drink 4 sips. Round 1: X and Y drink 5 sips now), with X and Y being the same names in both rounds.

First we made a small console app that had the challenges hardcoded in them. The list of challenges would look like this:

challenge_list = [
    Challenge(["p(0)", "rand_phone_number()"],[[0, "{d[0]} moet een nummer bellen. Het volgende scherm bepaalt welk nummer"], [1, "Het nummer is {d[1]}"]]),
    Challenge(["p(0)", "rand(2,5)", "rand_char('a','z')", "rand(2,5)"], [[0, "{d[0]} noemt {d[1]} dieren die beginnen met de letter {d[2]} of drinkt {d[3]} slokken"]]),
    Challenge([], [[0, "Alle drankjes schuiven een plek naar links"]]),

After requests from other friends we decided that it would be educational to migrate the project to Django, since we did not have much experience in web development and we want to learn something new. We came up with the following model to replicate the hardcoded challenges above:

class Challenge(models.Model):
    pass


class Var(models.Model):
    challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

class Round(models.Model):
    challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
    index = models.IntegerField()
    description = models.CharField(max_length=100)

    def __str__(self):
        return f"[{self.index},{self.description}]"

The only problem we face now is how can we query the data so that we retrieve a challenge object with the according vars and rounds, since in fact no data is saved inside the Challenge table except for a pk.

What we expect: A list of challenge objects with all the associated variables and rounds. E.g lets say we have the following entries in the DB

Challenge (has att pk)

1

2

3

Vars (has att pk, challenge fk and name) 1 1 "Var1"

2 1 "Var2"

3 2 "Var3"

4 3 "Var4"

5 3 "Var5"

In this example the first challenge has two variables, the second challenge has one variable and the third challenge has two variables.

Rounds (has att pk, fk for challenge, index, description

1 1 0 "{Var1} and {Var2} can only talk in french"

2 1 1 "{Var1} and {Var2} can stop talking french"

In this example, a challenge has multiple rounds. On pressing a "Next challenge" button, we want to retrieve the challenge, play the challenge with index 0 and put the other challenges inside a queue.

With the hardcoded example above, we made a challenge object and hardcoded the variables inside a list. This would be a bad practice upon having numerous challenges. That is why we want to have our challenges inside a db.

We are unsure how to correctly retrieve the challenges from the database but we suppose one way would be to retrieve all the variables and rounds associated with the challenge and put them inside an object (so it looks similar to the hardcoded example, except information is retrieved from a db and we can seperate our data from our logic).

Thanks for any help in advance and have a great day :)

Upvotes: 0

Views: 70

Answers (2)

Vitor Diniz
Vitor Diniz

Reputation: 363

In Django every model (unless explicitly specified) that has a reverse relationship (when the key is declared in the other model) has an interface called related manager that you can use to build queries and do lookups referring to the model where the relationship was defined. In your case since related_name was not specified in the ForeignKey fields, the related manager in Challenge was created using the _set suffix.

So to query challenges by looking up var and round:

Challenge.objects.filter(var_set__name='var_example')
Challenge.objects.filter(round_set__name='round_example')

I recommend you to read more about how querysets and relationship lookups work in django;

Upvotes: 1

Tom Carrick
Tom Carrick

Reputation: 6616

It looks like you want everything? Correct me if I'm misunderstanding.

# Get all challenges
challenges = Challenge.objects.all()

for challenge in challenges:
    # From here you have access to everything.
    # E.g. access all the rounds:
    for round in challenge.round_set.all():
        print(round.description)
    for var in challenge.var_set.all():
        print(var.name)

So what you want already exists. You can simply query the challenges and get the data from the reverse relationships. Relevant documentation.

Upvotes: 0

Related Questions