pythondjangorestorm

Django: How to add objects to ManyToManyFields of multiple objects in a fast way?


We have models.py file :

class Car(models.Model):
    brand = models.CharField(max_length=50 , null=True , blank=True)
    sub_brand = models.CharField(max_length=50 , null=True , blank=True)
    code = models.CharField(max_length=20 , unique=True)

class Skill(models.Model):
    car = models.ForeignKey(Car , on_delete=models.CASCADE, null=True , blank=True)
    skill = models.CharField(max_length=50 , null=True , blank=True)

class Provider(models.Model):
    name = models.CharField(max_length=100)
    skills = models.ManyToManyField(Skill , blank=True)

and we want to add some skills based on cars to the provider model so I use views.py like this:

def skills_add(request , id):
    provider = get_object_or_404(Provider , id=id)
    if request.method == 'POST':
        form = AddSkill(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            cars = Car.objects.filter(brand=data['brand'])

        for i in cars:
            for x in data['skills']:
                skill = Skill.objects.get(car=i , skill=x)
                provider.skills.add(skill)
                provider.save()
    else:
        return redirect("managers:dashboard_manager")
return redirect(request.META.get('HTTP_REFERER'))

the data["brand"] is a string of one brand of car and data["skills"] is a list of strings that each one of them are name of one skill that we have in out database. you send the data to form and then it's start to filter cars with that brand . after that , We start to loop over those cars and loop over the skills that sended . We add each one of them to skills field of the provider.

But the problem of this code is it's really slow! What can i do for this?


Solution

  • it's solved by using some lookups in django . So the views.py must be like this :

    def skills_add(request , id):
        provider = get_object_or_404(Provider , id=id)
        if request.method == 'POST':
            form = AddSkill(request.POST)
            if form.is_valid():
                data = form.cleaned_data
    
                if data['brand'] and data['sub_brand'] == "all":
                    cars = Car.objects.filter(brand=data['brand'])
                else:
                    cars = Car.objects.filter(brand=data['brand'] , sub_brand=data['sub_brand'])
            
                skill = Skill.objects.filter(car__in=cars , skill__in=data['skills']).values_list('id' , flat=True)
                provider.skills.add(*skill)
                provider.save()
        
            else:
                return redirect("managers:dashboard_manager")
        return redirect(request.META.get('HTTP_REFERER'))
    

    this way increase the speed of function about x10 times faster!