this code has this error and I am absolutely lost how to fix it. the code runs fine until it gets to the last object saved in the database and after that it throws this error. the code is a tool that checks the html of a website between 2 points in time to check if it has an error, even if the website is running well and giving a 200 response code
This is the error:
in check_html print(monitor.url) AttributeError: 'QuerySet' object has no attribute 'url'
def run_monitors():
delete_from_db()
monitors = Monitor.objects.filter(is_active=True)
monitors._fetch_all()
asyncio.run(_run_monitors(monitors))
check_html(monitor=monitors)
def check_html(monitor):
start_time = time.time()
print(monitor.url)
# The URLs to compare
old_html = monitor.html_compare
new_url = monitor.url
# Get the HTML of each URL
try:
old_html = old_html
# html1.raise_for_status()
except Exception as e:
print(e)
try:
html2 = requests.get(new_url)
html2.raise_for_status()
except Exception as e:
print(e)
return None
html2 = html2.text[:10000]
# Create a SequenceMatcher object to compare the HTML of the two URLs
matcher = difflib.SequenceMatcher(None, old_html, html2)
similarity_ratio = matcher.ratio() * 100
response_time = time.time() - start_time
monitor.html_compare = html2
html_failure = False
counter = monitor.fault_counter
if similarity_ratio <= 90 and counter == 0:
print(f"The two HTMLs have {similarity_ratio:}% in common.")
print("change detected")
html_failure = False
counter = 1
elif similarity_ratio > 90 and counter == 0:
print(f"The two HTMLs have {similarity_ratio:.2f}% in common.")
print("no change detected")
html_failure = False
counter = 0
elif similarity_ratio > 90 and counter >= 1:
print(f"The two HTMLs have {similarity_ratio:.2f}% in common.")
if counter >= 4:
print(f"HTML fault detected")
html_failure = True
else:
counter = 1
print(f"checks if fault persists, current fault counter: {counter}")
elif similarity_ratio < 90 and counter >= 1:
print("Fault is presumably resolved")
html_failure = False
counter = 0
monitor.fault_counter = counter
# Print the similarity ratio between the two URLs
monitor.save(update_fields=['html_compare', 'fault_counter'])
return html_failure
def send_notifications():
for monitor in Monitor.objects.all():
multiple_failures, last_result = has_multiple_failures(monitor)
result = check_html(monitor)
no_notification_timeout = (not monitor.last_notified) or \
monitor.last_notified < timezone.now() - timedelta(hours=1)
if multiple_failures and no_notification_timeout and monitor.is_active:
_send_notification(monitor, last_result)
if result:
_send_notification(monitor, last_result)
I already tried to put a for loop around the 'check_html' function that iterates over every object in monitor but that just returns that monitors can't be iterated over. it was a long shot but still didn't work
CodePudding user response:
You have passed the queryset to the check_html()
function. Using a filter we get one or more items that are iterable. You can use the for loop in check_html()
function or password only one object to the function.
CodePudding user response:
everybody, I found the issue. so I added the function check_html to run on a certain command. which at the end of the script tried to give the whole queryset to the check_html function itself.
so I just had to remove the check_html function from run_monitor.
thank you for your help guys