Django: Как добавить в базу данных с помощью цикла corectly?

Я пытаюсь сохранить в базе данных все бои для данной группы (каждый с каждым) одновременно из формы, взяв количество раундов для каждого из боев, пока что функция ничего не добавляет в базу данных. Я не уверен, можно ли ее добавить в цикле типа такого, следуя списку пар: [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)] и обращаться к индексам элементов списка при создании объектов боев для сохранения

def add_fights(request, group_id):
    group = Group.objects.get(pk=group_id)
    tournament = group.tournament
    participants = group.participants.all()
    participants_ids = participants.values('id')
    only_ids_ls = [i.get('id', 0) for i in participants_ids]
    participants_pairs = list(itertools.combinations(only_ids_ls, 2))
    group.fighters_one = [p[0] for p in participants_pairs]
    group.fighters_two = [p[1] for p in participants_pairs]
    print(participants_pairs)
    if request.user.is_authenticated:
        form = AddGroupForm(request.POST)
        if request.method == "POST" and form.is_valid():
            rounds = form.cleaned_data['rounds']
            obj = form.save(commit=False)
            if obj:
                for p in participants_pairs:
                    obj.group = group
                    obj.rounds = rounds
                    obj.tournament = tournament
                    obj.fighter_one = group.participants.get(id=p[0])
                    obj.fighter_two =group.participants.get(id=p[1])
                    obj.save()
                    print("obj")
                    print(obj)
                    group.fights.create(group=group, rounds=rounds, tournament=tournament, fighter_one=obj.fighter_one, fighter_two=obj.fighter_two)
                    return HttpResponseRedirect(reverse("tournaments:tournament_details", args=[group_id]))
        else:
            form = AddFightsForm
            return (
                render(request, "add_fights.html", context={
                    'form': form,
                    'group_id': group_id,
                })
            )

модели:

from django.db import models
from django.contrib.auth.models import User
from sorl.thumbnail import ImageField
from datetime import datetime


class Organizer(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    image = ImageField(upload_to="organizers/logos/%Y/%m/%d/", blank=True, null=True)
    user = models.ForeignKey("auth.User", on_delete=models.CASCADE, default=1, related_name="organizers_created")

    def __str__(self):
        return f"{self.name} {self.description} {self.image} "

    class Meta:
        verbose_name = "Organizator"
        verbose_name_plural = "Organizatorzy"


class Tournament(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    organizers = models.ManyToManyField('Organizer', related_name="tournaments")
    image = ImageField(upload_to="tournaments/logos/%Y/%m/%d/", blank=True, null=True)
    user = models.ForeignKey("auth.User", on_delete=models.CASCADE, related_name="tournaments_created")
    created = models.DateTimeField(auto_now=True, null=True)
    modified = models.DateTimeField(auto_now=True, null=True)

    def __str__(self):
        return f"{self.id} {self.title} {self.description} {self.image}"

    class Meta:
        verbose_name = "Turniej"
        verbose_name_plural = "Turnieje"

Я не уверен, спрашиваете ли вы, можно ли CAN создавать объекты в таком цикле или нужно ли это делать.

Да, вы можете сделать это, но поскольку вы пытаетесь создать несколько экземпляров одной модели одновременно, я бы предложил использовать bulk_create:

https://docs.djangoproject.com/en/4.1/ref/models/querysets/#bulk-create

Он улучшает скорость вставки, пытаясь выполнить их все одновременно вместо нескольких отдельных вызовов вставки в БД вашим кодом Python.

Плюс, я вижу, что в вашем цикле for вы возвращаете HttpResponseRedirect, но вы делаете это снова и снова для каждой пары участников.

Возможно, достаточно сделать это один раз.

<
Вернуться на верх