Reputation: 65
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.
Upvotes: 1
Views: 3619
Reputation: 4819
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})
Upvotes: 3
Reputation: 3700
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
Upvotes: 1