None вместо пустого экземпляра Object?
Я пытаюсь создать веб-сайт Secret Santa, используя Python Django. У меня возникает проблема, когда количество участников нечетное. Я использую встроенную в Django модель User и сопоставляю ее экземпляры как совпадения для игры. В случае нечетного количества участников, будет участник без пары. Есть ли способ сохранить None в случае пустого экземпляра без возникновения ValueError?
Вот мой код:
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
Любая помощь или предложение будут полезны.
EDIT Вот трассировка ошибки:
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.
Queryset.filter
возвращает новый объект Queryset. Вместо этого вы хотите использовать Queryset.get(pk=...)
или Queryset.filter(...).first()
.
Вы также можете полностью избежать дополнительных вызовов db, например, проиндексировав всех пользователей по их первичному ключу: id_to_user = {_.pk: _ for _ in participants}