i am building an amazon web scraper where you can submit a link and track the price of your product.
When i try to go to this site this error pops up and it also says that the error is at line 0 at base.html
How do i get rid of this error
models.py
from django.db import models
from .utils import get_link_data
# Create your models here.
class Link(models.Model):
name = models.CharField(max_length=220, blank=True)
url = models.URLField()
current_price = models.FloatField(blank=True)
old_price = models.FloatField(default=0)
price_difference = models.FloatField(default=0)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.name)
class Meta:
ordering = ('price_difference', '-created')
def save(self, *args, **kwargs):
name, price = get_link_data(self.url)
old_price = self.current_price
if self.current_price:
if price != old_price:
diff = price - old_price
self.price_difference = round(diff, 2)
self.old_price = old_price
else:
self.old_price = 0
self.price_difference = 0
self.name = name
self.current_price = price
super().save(*args, **kwargs)```
**views.py**
```from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from .models import Link
from .forms import AddLinkForm
from django.views.generic import DeleteView
def home_view(request):
no_discounted = 0
error = None
form = AddLinkForm(request.POST or None)
if request.method == 'POST':
try:
if form.is_valid():
form.save()
except AttributeError:
error = "Ups ... couldn't get the name or the price"
except:
error = "Ups ... something went wrong"
form = AddLinkForm()
qs = Link.objects.all()
items_no = qs.count()
if items_no > 0:
discount_list = []
for item in qs:
if item.old_price > item.current_price:
discount_list.append(item)
no_discounted = len(discount_list)
context = {
'qs': qs,
'items_no': items_no,
'no_discounted': no_discounted,
'form': form,
'error': error,
}
return render(request, 'links/main.html', context)
class LinkDeleteView(DeleteView):
model = Link
template_name = 'links/confirm_del.html'
success_url = reverse_lazy('home')
def update_prices(request):
qs = Link.objects.all()
for link in qs:
link.save()
return redirect('home')
base.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<title>My amazon price tracker</title>
</head>
<body>
<div class="container mt-3">
{% block content %}
{% endblock content %}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
</html>
main.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<!-- Modal -->
<div class="modal fade" id="addItemModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add an Item for Tracking</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="" method="POST" autocomplete="off">
{% csrf_token %}
{{form|crispy}}
<button type="submit" class="btn btn-primary mt-2">Save</button>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col text-left">
<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#addItemModal">Add</button>
<a href="{% url 'update_prices' %}">
<button class="btn btn-info">Update</button>
</a>
</div>
<div class="col" style="text-align:right">
<div>Total Number of Items Being Tracked: {{items_no}}</div>
<div>Total Number of Discounted Items: {{no_discounted}}</div>
</div>
</div>
{% if qs %}
{% for item in qs %}
<div class="card mt-3">
<div class="card-header">
<h5>{{item.name}}</h5>
<a href="{% url 'delete' item.pk %}"><button class="btn btn-danger">Delete</button></a>
</div>
<div class="card-body">
<div class="blockquote">
<div>Current Price ($): {{item.current_price}}</div>
<div>Original Price ($): {{item.old_price}}</div>
<div>Difference ($): {{item.price_difference}}</div>
<div>Link: <a href="{{item.url}}" target="_blank">{{item.url}}</a></div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<h3> No Items Being Tracked</h3>
{% endif %}
{% endblock content %
}```
**confirm_del.html**
{% extends "base.html" %}
{% block content%}
<form method="POST" action="">
{% csrf_token %}
<p>Are You Sure You Want To Delete The Link: "{{object.name}}"</p>
<div>
<button type="submit" class="btn btn-primary">Yes</button>
<a href="{% url 'home' %}"><button class="btn btn-danger">Cancel</button></a>
</div>
</form>
{% endblock content%}
**urls.py**
from django.contrib import admin
from django.urls import path
from links.views import home_view, update_prices, LinkDeleteView
```urlpatterns = [
path('admin/', admin.site.urls),
path('', home_view, name='home'),
path('update/', update_prices, name='update-prices'),
path('delete/<pk>/', LinkDeleteView.as_view(), name="delete"),
]```
**utils.py**
```import requests
from bs4 import BeautifulSoup
import lxml
def get_link_data(url):
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
"Accept-Language": "en"
}
r = requests.get(url, headers=headers)
soup = BeautifulSoup(r.text, "lxml")
name = soup.select_one(selector="#productTitle").getText()
name = name.strip()
price = soup.select_one(selector="#priceblock_ourprice").getText()
price = float(price[1:])
return name, price
settings.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'links',
'crispy_forms',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'amazon_web_scraper.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'amazon_web_scraper.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserA