2

What I'm trying to do is saving multiple scraped data(actor names) in my Actor table inside Django models.

So far I've written the for loop below to achieve this goal but it only saves the last object.

class Actor(models.Model):
    name = models.CharField(max_length=50)
    url = models.URLField()

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        i = 0
        for num in range(5):
            title, year, actor_list = scraper(self.url)
            self.name = actor_list[i]
            super().save(*args, **kwargs)
            i += 1

I get the URL from users within a form, then save the form and send it to my models and the scraping begins.

I scrape 5 actor names inside the scraper() function and append them to actor_list.

But when I try to save the actor_list under the save function, it only saves the 5th actor which I think overwrites the previously saved objects.

Is there something wrong with my for loop? or should I completely change my approach for this purpose?

I'd also prefer to save the objects using Actor.objects.get_or_create() to skip the already existing objects, but I don't know how and where.

I would appreciate it if someone could help me with this.

2 Answers 2

3

Yes, you should use a completely different approach. A Model is just a code representation of your database table.

You are also executing the same scraping 5 times on the same url, but that is another point.

Doing scraping and creating multiple actors should not be done within the model. Bear in mind that the model gets instantiated as an actor object (a single record in the actor table), so every time you do a super().save() it overwrites the same record.

The standard way is to do it in the view you use to print the form and have that form submit to its own URL (i.e. the form action should point to the same view you use to print it).

Something like this:

forms.py

from django import forms

class MyForm(forms.Form):
    url = forms.CharField(label='Your name', max_length=255)

views.py

from my_app.forms import MyForm
from my_app.models import Actor
from django.shortcuts import render

def my_view(request):
    if request.method == "POST":
        form = MyForm(request.POST)
        if form.is_valid():
            title, year, actor_list = scraper(form.cleaned_data['url'])
            for actor in actor_list:
                # Here you are creating new instances of Actor (new records) 
                # at each iteration, unless they already exist.
                Actor.objects.get_or_create(name=actor)
    else:
        form = MyForm()
    return render(request, 'your_template.html', {'form': form})
Sign up to request clarification or add additional context in comments.

2 Comments

Your code works very fine. Thanks a lot for the explanation too. I'm new to Django and I completely understood the concept here. @MarcCompte
You wrote a good question, that always makes it easier to get a good answer. Glad I could help to fix the error and even better if you learned something for the future.
1

The save() method acts on a single Actor object. It's wrong to try to save multiple actors there.

Do this in a view:

title, year, actor_list = scraper(self.url)
for i in range(5):
    actor = Actor()
    actor.name = actor_list[i]
    actor.save()

And delete the save() method in the model

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.