Fatima
Fatima

Reputation: 61

None instead of empty Object instance?

I'm trying to create Secret Santa web site using Python Django. Issue I have is when there's odd number of participants. I'm using Django's built in User model and pairing its instances as matches for the game. In case of odd number, there will be a participant without match. Is there any way to store None in case of empty instance without raising ValueError?

Here's my code:

models.py

class Participants (models.Model):
    giver = models.OneToOneField(User, on_delete=models.CASCADE, null = True, blank = True, related_name = "giver")
    receiver = models.OneToOneField(User, on_delete=models.CASCADE, null = True, blank = True, related_name = "receiver")

    def __str__(self):
        return self.receiver.username

views.py

def matchPairs(request):
    participants = User.objects.all().exclude(is_superuser=True)
    participants_names = [p.id for p in participants]
    i = 0
    Givers = []
    Receivers = []
    if request.method == "POST":
        [givers, receivers] = pairs_generator.generate_match(participants_names)
        while i < len(receivers):
            if givers[i] == None:
                Givers.append(None) 
            else:
                Givers.append(User.objects.filter(pk = givers[i]))
            Receivers.append(User.objects.filter(pk = receivers[i]))
            
            Participants.objects.create(giver = Givers[i], receiver = Receivers[i])
            messages.success(request, "Matching successful! Here's the list.")
            return redirect('participants')
    else:
        messages.error(request, "Woops. Something went wrong. Please try again.")
        return redirect('participants')

generate_match.py

def generate_match(participants_names):
    givers = []
    receivers = []
    flag = None
    random.shuffle(participants_names)
    i = 0
    while i < len(participants_names):
      if (is_even(participants_names)):
          print(f'{participants_names[i]} exchanges gifts with {participants_names[i + 1]}. ')
          givers.append(participants_names[i])
          receivers.append(participants_names[i+1])
          i += 2 
      else:
          print(f'{participants_names[i]} has no one to buy a gift to this year. :(')
          givers.append(flag)
          receivers.append(participants_names[i])
          participants_names.pop(i)
    return givers, receivers

Any help or suggestion would be helpful.

EDIT Here's error traceback:

Traceback (most recent call last):
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/santa/secretsanta/views.py", line 44, in matchPairs
    Participants.objects.create(giver = Givers[i], receiver = Receivers[i])
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/db/models/query.py", line 455, in create
    obj = self.model(**kwargs)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/db/models/base.py", line 489, in __init__
    _setattr(self, field.name, rel_obj)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 310, in __set__
    super().__set__(instance, value)
  File "/Users/fatimavelic/Documents/Doing/projects/penv/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 215, in __set__
    raise ValueError(

Exception Type: ValueError at /secretsanta/match-pairs/
Exception Value: Cannot assign "<QuerySet [<User: Daisy>]>": "Participants.receiver" must be a "User" instance.

Upvotes: 0

Views: 386

Answers (1)

Nielk
Nielk

Reputation: 760

Queryset.filter returns a new Queryset oject. You want to use Queryset.get(pk=...) instead, or Queryset.filter(...).first() You could also avoid extra db calls completely, for example by indexing all users by their primary key: id_to_user = {_.pk: _ for _ in participants}

Upvotes: 2

Related Questions