I’m trying to override the save method on a model so that is can compare the domain contained in a link being added to the main model and select that domain from a foreign key model, to automatically save that domain as the foreign key value without me having to manually select it in the Django Admin interace.
However, I get Cannot assign ... must be an instance
errors even though the expected value is already in the foreign key table, for example:
ValueError: Cannot assign "'www.theguardian.com'": "Link.source" must be a "Source" instance.
I’m not sure if it is impossible to automate this in a model method, but here are my models:
from django.db import models
from bs4 import BeautifulSoup # for scraping
from urllib.parse import urlparse
import requests # for scraping
class Source(models.Model):
netloc = models.CharField(max_length=50, unique=True)
class Meta:
ordering = ['netloc']
def __str__(self):
return self.netloc
class Link(models.Model):
url = models.URLField(max_length=200, unique=True, verbose_name='URL')
title = models.CharField(max_length=120, unique=True, blank=True,
help_text = 'Set manually if scraped title is not suitable')
source = models.ForeignKey('Source',
on_delete=models.PROTECT, to_field='netloc', default='000.example.org',
)
...
def get_scraped_title(self):
reqs = requests.get(self.url)
soup = BeautifulSoup(reqs.text, 'html.parser')
return soup.title.get_text()
def get_netloc(self):
return urlparse(self.url).netloc
def save(self, *args, **kwargs):
if not self.title:
self.title = self.get_scraped_title()
self.source = self.get_netloc()
super(Link, self).save(*args, **kwargs)