Django. Объект типа Url не является сериализуемым в JSON
Я пишу парсер для сайта. У меня есть 2 модели: Url (id и url сайта) и News (все данные, которые будут разобраны)
Я сделал форму, которая позволяет пользователям вводить ссылку сайта, которая автоматически сохраняется в db. А также у меня есть сигнал, который начинает парсить данные, как только экземпляр Url сохраняется. Но дело в том, что когда я вызываю функцию hackernews_rss, которая разбирает данные, я получаю ошибку
kombu.exceptions.EncodeError: Object of type Url is not JSON serializable
Я не знаю, как это исправить, так как для сохранения всех результатов парсинга мне необходимо иметь экземпляр Url из-за OneToManeRelation
модели:
class Url(models.Model):
link = models.CharField(
max_length=200,
blank=True
)
def get_absolute_url(self):
return f'/parser/search/'
class News(models.Model):
domain = models.CharField(max_length=200)
link_id = models.ForeignKey(Url, on_delete=models.CASCADE)
link = models.CharField(max_length=200, blank=True)
create_date = models.DateTimeField()
update_date = models.DateTimeField()
country = models.CharField(max_length=200, null=True)
is_dead = models.BooleanField()
a = models.CharField(max_length=200, null=True)
ns = models.CharField(max_length=200, null=True)
cname = models.CharField(max_length=200, null=True)
mx = models.CharField(max_length=200, null=True)
txt = models.CharField(max_length=200, null=True)
задачи:
@shared_task(serializer='json')
def save_function(article_list):
print('starting')
new_count = 0
for article in article_list:
try:
print(article['link_id'])
News.objects.create(
link=article['link'],
domain=article['domain'],
create_date=article['create_date'],
update_date=article['update_date'],
country=article['country'],
is_dead=article['is_dead'],
a=article['a'],
ns=article['ns'],
cname=article['cname'],
mx=article['mx'],
txt=article['txt'],
link_id = article['link_id']
)
new_count += 1
except Exception as e:
print('failed at latest_article is none')
print(e)
break
return print('finished')
@shared_task
def hackernews_rss(url, url_id, instance):
print(url, url_id)
article_list = []
try:
print('Starting the Scrapping tool')
r = requests.get(url)
soup = BeautifulSoup(r.content, features='lxml')
container = soup.select('a')
url_storage = []
for block in container:
try:
url1 = block.get('href')
if url1.startswith('http'):
url_storage.append(url1)
except:
continue
for link in url_storage:
r = requests.get(f'https://api.domainsdb.info/v1/domains/search?domain={link}')
data = r.text
parse_json = json.loads(data)
for block in parse_json['domains']:
domain = block['domain']
create_date = block['create_date']
update_date = block['update_date']
country = block['country']
is_dead = block['isDead']
a = block['A']
ns = block['NS']
cname = block['CNAME']
mx = block['MX']
txt = block['TXT']
article = {
'domain': domain,
'link': link,
'create_date': create_date,
'update_date': update_date,
'country': country,
'is_dead': is_dead,
'a': a,
'ns': ns,
'cname': cname,
'mx': mx,
'txt': txt,
'link_id': url_id
}
article_list.append(article)
print('Finished scraping the articles')
return save_function(article_list)
except Exception as e:
print('The scraping job failed. See exception:')
print(e)
сигналы:
@receiver(post_save, sender=Url)
def notify_subscribers(sender, instance, created, **kwargs):
if created:
url_instance = instance.link
url_id = instance.id
hackernews_rss.delay(url_instance, url_id, instance)
просмотров:
class HomePageView(generic.ListView):
template_name = 'home.html'
context_object_name = 'articles'
paginate_by = 7
queryset = News.objects.order_by('create_date')
form_class = ParserForm
def get_queryset(self):
queryset = super().get_queryset()
return ParserFilter(self.request.GET, queryset=queryset).qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = ParserFilter(self.request.GET, queryset=self.get_queryset())
return context
class UrlCreateView(generic.CreateView):
template_name = 'url_create.html'
form_class = CreateForm
model = Url
Формы:
class CreateForm(ModelForm):
class Meta:
model = Url
fields = ['link']
Должен признаться, что раньше я не указывал экземпляр hackernews_rss в качестве аргумента. Я хотел создать отношение по link_id: 'link_id': url_idl_. Но celery выдал следующую ошибку:
Cannot assign "15": "News.link_id" must be a "Url" instance.