<django.db.models.query_utils.DeferredAttribute object at ... > вместо значения данных в базе данных PostgreSQL
Я пытаюсь отобразить значение на html-странице, но значение просто возвращается как <django.db.models.query_utils.DeferredAttribute object at ... >. Проблема заключается в переменной 'card_name'.
Вот мои файлы кода из моего проекта Django:
Models.py:
class mProSet1990(models.Model):
Image = models.CharField(max_length=255, primary_key=True)
Card = models.CharField(max_length=255)
class Meta:
managed = False
db_table = '1990 Pro Set'
Views.py:
def ProSet1990_1(request):
# Fetch the card details from the database
card_1 = mProSet1990.objects.get(Card="David Seaman #1")
# Use the web scraping bot to get the lowest card price
lowest_price = get_lowest_card_price(f'{mProSet1990.Set} {mProSet1990.Card}')
# Pass the data to the template
context = {
'card_1': card_1,
'card_name': mProSet1990.Card,
'lowest_price': lowest_price,
}
# Render the template with the data
return render(request, 'Application/ProSet1990_1.html', context)
ProSet1990_1.html body:
<body>
<h1>{{ card_name }}</h1>
{% if lowest_price %}
<p>Lowest Price: {{ lowest_price }}</p>
{% else %}
<p>Price not available</p>
{% endif %}
</body>
mProSet1990.Set и mProSet1990.Card не извлекают фактические значения, они возвращаются как объект <django.db.models.query_utils.DeferredAttribute по адресу ... >.
В вашем коде есть несколько ошибок. Вы передаете атрибуты неустановленного класса mProSet1990
, а не значения возвращаемого запроса card_1
. Это проблема как для lowest_price
, так и для context
. Это просто исправить (измените контекст на "card_name": card_1.Card
). Однако вместо этого я бы рекомендовал использовать следующее:
models.py
class mProSet1990(models.Model):
Image = models.CharField(max_length=255, primary_key=True)
Card = models.CharField(max_length=255)
class Meta:
managed = False
db_table = '1990 Pro Set'
def get_lowest_price(self):
# BUG: This model does not define `Set`!
return get_lowest_card_price(f'{self.Set} {self.Card}')
views.py
def ProSet1990_1(request):
card = mProSet1990.objects.get(Card="David Seaman #1")
lowest_price = get_lowest_card_price(f'{card.Set} {card.Card}')
context = {
'card': mProSet1990.objects.get(Card="David Seaman #1"),
}
return render(request, 'Application/ProSet1990_1.html', context)
ProSet1990_1.html
<body>
<h1>{{ card.Card }}</h1>
{% with card.get_lowest_price as lowest_price %}
{% if lowest_price %}
<p>Lowest Price: {{ lowest_price }}</p>
{% else %}
<p>Price not available</p>
{% endif %}
{% endwith %}
</body>
При этом я бы пошел гораздо дальше. В Django довольно много батарей, и вы делаете лишнюю работу, чтобы воссоздать то, что уже делает DetailView
. Кроме того, у вас не очень хорошая модель данных. Я бы начал с чего-то вроде следующего.
app_name/models.py
from decimal import Decimal
import requests
from django.db import models
class Collection(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
def __str__(self):
return self.name
def update_cards(self):
cursor = None
while True:
response = requests.get(
f"https://www.sportscardspro.com/console/{self.slug}",
params={"cursor": cursor, "format": "json"},
timeout=5,
)
response.raise_for_status()
data = response.json()
for product in data["products"]:
parsed = Card.parse_api_data(product)
Card.objects.update_or_create(slug=parsed["slug"], defaults=parsed)
cursor = data.get("cursor")
if not cursor:
break
class Card(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
image = models.ImageField(null=True, blank=True)
ungraded_price = models.DecimalField(max_digits=10, decimal_places=2)
grade_9_price = models.DecimalField(max_digits=10, decimal_places=2)
grade_10_price = models.DecimalField(max_digits=10, decimal_places=2)
collection = models.ForeignKey(Collection)
def __str__(self):
return self.name
@classmethod
def parse_api_data(cls, data):
return {
"name": data["productName"],
"slug": data["productUri"],
"image": cls.download_image(data["imageUri"]),
"ungraded_price": cls.parse_price(data["price1"]),
"grade_9_price": cls.parse_price(data["price3"]),
"grade_10_price": cls.parse_price(data["price2"]),
}
@classmethod
def parse_price(cls, price):
return Decimal(price.replace("$", "").replace(",", ""))
@classmethod
def download_image(cls, url):
# Code to download the image and populate self.image.
# Example: https://stackoverflow.com/questions/16174022/download-a-remote-image-and-save-it-to-a-django-model
return None
app_name/views.py
from django.views.generic.detail import DetailView
from .models import Card
class CardDetailView(DetailView):
model = Card
app_name/urls.py
from django.urls import path
from .views import CardDetailView
urlpatterns = [
path("<slug:slug>/", CardDetailView.as_view(), name="card-detail"),
]
app_name/templates/app_name/card_detail.html
<body>
<h1>{{ object }}</h1>
<p>Ungraded: ${{ object.ungraded_price }}</p>
<p>Grade 9: ${{ object.ungraded_price }}</p>
<p>PSA 10: ${{ object.ungraded_price }}</p>
</body>