<django.db.models.query_utils.DeferredAttribute object at ... > instead of data value in PostgreSQL database

I am trying to display a value on an html page but the value is just returning as <django.db.models.query_utils.DeferredAttribute object at ... >. The issue is the variable 'card_name'.

This is my code files from my Django project:

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 and mProSet1990.Card are not pulling the actual values, they are returning as <django.db.models.query_utils.DeferredAttribute object at ... >.

There are several errors in your code. You're passing around attributes of the uninstantiated class mProSet1990, not the values of the returned query card_1. This is a problem for both lowest_price and context There's a simple fix (change the context to "card_name": card_1.Card). However, I'd recommend the following instead:

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>

That being said, I'd go quite a lot further than this. Django is fairly batteries-included, and you're doing extra work here to re-create what DetailView already does. You also don't have a very good data model started here. I'd begin with something like the following.

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>
Back to Top