1

Imagine I have a model Monster and model Fight that assigns users to monsters.

class Fight(models.Model):
    fight_user = models.OneToOneField(User, on_delete=models.CASCADE)
    fight_enemy = models.ForeignKey(Monster, on_delete=models.CASCADE)

Now, if a user (fight_user) does not have already a Fight instance asociated to it, I want to create one by selecting randomly an instance from the Monster model.

How can I do that?

Ralf
  • 16,086
  • 4
  • 44
  • 68
Eleyox
  • 33
  • 6
  • 1
    Possible duplicate of [How to pull a random record using Django's ORM?](https://stackoverflow.com/questions/962619/how-to-pull-a-random-record-using-djangos-orm) – bonidjukic Feb 18 '18 at 22:53

1 Answers1

0

A few things to consider:

  1. Do you want this to be a process that you launch once to fill in every user that has no Fight instance associated? This could be done inside a POST view.
  2. Can different users fight the same monster or should each face a different one? In the later case, what should happen if there aren't enough monsters available?

In a comment to your question, user @bonidjukic linked this post, but that only applies if you want to pull a single monster randomly.

Since you would assign a random monster to all users without a fight, I propose loading all monsters into a list and select randomly from there till all users have a fight. See my code below:

import random
from django.contrib.auth.models import User
from .models import Fight, Monster


def get_available_monsters(only_one_fight_per_monster):
    monster_qs = Monster.objects.all()

    if only_one_fight_per_monster:
        # only monster that do NOT have a fight already
        monster_qs = monster_qs.filter(fight__isnull=True)

    # convert to list
    # if you have many thousand monsters, this approach might not be the best
    return list(monster_qs)


def create_fights(only_one_fight_per_monster):
    monster_list = get_available_monsters(only_one_fight_per_monster)

    # all users without a fight
    for usr in User.objects.filter(fight__isnull=True):
        i = random.randrange(0, len(monster_list))

        f = Fight()
        f.fight_user = usr
        f.fight_enemy = monster_list[i]
        f.save()

        if only_one_fight_per_monster:
            monster_list.pop(i)

This might fail if there are more users than monsters if each users fights a different monster.

Let me know if this helps you, even if the answer is a bit late.

Ralf
  • 16,086
  • 4
  • 44
  • 68