0

this is the code in views.py

def store (request):

    products = {
       'products':product.objects.all()
    }

    return render (request, 'neizer/products.html', context = products)

this is the template

{% block content %}

<div class="products-parent">
  {%for product in products%}
  <div class="product-child">
    <img src={{product.image.url}} alt="no image available" />
    <h2>{{product.name}}</h2>
    <button id="learn-more-btn">learn more</button>
    <p>${{product.price}} <i class="fas fa-cart-plus"></i></p>
  </div>

  {% endfor %}
</div>
{% endblock content %}

I uploaded images using the /admin interface, when i access the image url in the django shell i get an actual url (which opens in the browser to the image), but when i try to access it in the template i get the above error, the issue as it seems is with the product.image.url, somehow django doesn't seem to get the class instance right. this is the traceback:

Traceback (most recent call last):
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 828, in _resolve_lookup
    current = current[bit]

During handling of the above exception ('ImageFieldFile' object is not subscriptable), another exception occurred:
  File "/mnt/s/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/mnt/s/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/mnt/s/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/mnt/s/webapp/main/views.py", line 20, in store
    return render (request, 'neizer/products.html', context = products)
  File "/mnt/s/env/lib/python3.6/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 986, in render
    output = self.filter_expression.resolve(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 670, in resolve
    obj = self.var.resolve(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 795, in resolve
    value = self._resolve_lookup(context)
  File "/mnt/s/env/lib/python3.6/site-packages/django/template/base.py", line 836, in _resolve_lookup
    current = getattr(current, bit)
  File "/mnt/s/env/lib/python3.6/site-packages/django/db/models/fields/files.py", line 61, in url
    self._require_file()
  File "/mnt/s/env/lib/python3.6/site-packages/django/db/models/fields/files.py", line 38, in _require_file
    raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)

Exception Type: ValueError at /store
Exception Value: The 'image' attribute has no file associated with it.

1 Answers1

2

The error occure because not all of your records have an image file associated. Most easy solution for this error is to check if there is an associated image:

{% if person.image %}
    <img src={{product.image.url}} />
{% else %}
    <img src="#" alt="no image available" />
{% endif %}

Another way is to actually have a default value for image field (default image):

image = models.ImageField(upload_to='whatever', default='your_default_image.jpg')

or at least put a default image in template:

...
{% else %}
    <img src="{% static 'your_default_img_path' %}" >
...

and yet another way is to user property for the model:

@property
def get_image_url(self):
    if self.image and hasattr(self.image, 'url'):
        return self.image.url
    else:
        return "/static/images/your_default_image.jpg"
Charnel
  • 4,222
  • 2
  • 16
  • 28
  • should fix the error for now but I can't use default images, it's supposed to be a pic of a product – ISAAC FINKELSTEIN Feb 10 '20 at 15:56
  • i get an associated image url when i try to access it in the django shell, so there obviously is an image associated with product instance – ISAAC FINKELSTEIN Feb 10 '20 at 15:57
  • `product.objects.all()` means that you're trying to display all existing records - are you sure all of them do have image set? – Charnel Feb 10 '20 at 16:11
  • but even if there isn't an image, you wouldn't get an error, the template would just render an empty string. – dirkgroten Feb 10 '20 at 16:14
  • @dirkgroten I'll disagree - image, if it's actually had associated file, do have `url` attribute because it's an attribute of associated file, but not a field itself. Without the file you're actually trying to get attribute of None. – Charnel Feb 10 '20 at 16:22
  • i am sure every product has an image associated with them – ISAAC FINKELSTEIN Feb 10 '20 at 16:23
  • 1
    Let's try something really simple - `Product.objects.filter(image__exact='').count()` Can you check if this return something greater then zero? – Charnel Feb 10 '20 at 16:30
  • @ISAACFINKELSTEIN be sure of what you want, it won't change facts: if you get this error then some of your records don't have an image, period. – bruno desthuilliers Feb 10 '20 at 16:31
  • @Charnel you're right, it raises a `ValueError` if the image is not set (note it doesn't try to get `url` from `None`, that would raise an `AttributeError`, which is what confused me in the original question). – dirkgroten Feb 10 '20 at 16:33
  • @Charnel please don't encourage hardcoding urls - this should use the staticfiles app for computing statics urls. – bruno desthuilliers Feb 10 '20 at 16:35
  • I deleted all the items and re-uploaded them, now it works seems like i changed the upload to at some point and forgot to re-upload the images, thanks a lot for your help – ISAAC FINKELSTEIN Feb 10 '20 at 16:50