django: How add to database by loop corectly?

Viewed 34

I am trying to save in the database all fights for a given group (everyone with everyone) at the same time from the form taking the number of rounds for each of the fights, so far the function does not add anything to the database. I am not sure if it can be added in a loop like this following the list of pairs: [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4 ), (2, 5), (3, 4), (3, 5), (4, 5)] and refer to the indexes of list items when creating combat objects to save

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,
                })
            )

models:

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"

1 Answers

I'm not sure if you are asking if you CAN create objects in a loop like that or if you should.

Yes you absolutely can do that, but since you are trying to create multiple instances of the same model all at once, I'd probably suggest looking at using a bulk_create:

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

It improves on the speed of the inserts by trying to run them all at once instead of multiple individual insert calls to the DB by your Python code.

Plus, I can see in your for loop you are returning a HttpResponseRedirect, but you are doing that over and over again for each participants_pair.

Probably just do it the once.

Related