Home > OS >  AttributeError: 'QuerySet' object has no attribute 'url'
AttributeError: 'QuerySet' object has no attribute 'url'

Time:12-17

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

  • Related