Django not getting images that are uploaded to sqlite - html

Images are not coming into template.
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
html
{% for question in question_list %}
<img src= "{{question.image}}">
models.py
class NewQuestion(models.Model):
category = models.ForeignKey(Category)
question_text = models.CharField(max_length = 200, unique = True, null = False)
image = models.ImageField(upload_to='images')
def __unicode__(self):
return self.question_text

To render a photo from an ImageField in Django's templating language, the following syntax is required:
{{ image.url }}
In your case:
{% for question in question_list %}
<img src= "{{ question.image.url }}">
{% endfor %}

Try this:
{% for question in question_list %}
<img src= "{{question.image.url}}">
{% endfor %}
Reference to docs:
A read-only property to access the file’s relative URL by calling the url() method of the underlying Storage class.
Update:
Adding this to your urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Related

NoReverseMatch at / when trying to add href in Django

I have a list of items and I am trying to add a link to the item's title to direct the user to the item's own page. However, I am getting Reverse for 'listing' with arguments '('',)' not found. 1 pattern(s) tried: ['listing/(?P<listing_id>[0-9]+)\\Z'] error and I couldn't figure out what I did wrong.
The error is in line<h2>{{auction.title}}</h2> of index.html
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("create", views.create_listing, name="create"),
path("listing/<int:listing_id>", views.listing, name = "listing"),
]
views.py:
def listing(request,listing_id):
listing = AuctionItem.objects.get(id = listing_id)
return render(request, "auctions/listing.html",{
"listing":listing
})
index.html:
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
{% for auction in auctions %}
<div class = "frame">
<img src="{{auction.image}}" style= "width: 30vw;">
<h2>{{auction.title}}</h2>
<div id="text"><strong>Price:</strong> ${{auction.price}}</div>
<div id="text"><strong>Description:</strong> {{auction.description}}</div>
<div id="text"><strong>Category:</strong> {{auction.category}}</div><br>
<div id="date">Created {{auction.date}}</div>
</div>
{% empty %}
<li>No item.</li>
{% endfor %}
{% endblock %}
The object is named auction in the context when rendering, so:
<h2>{{auction.title}}</h2>
or perhaps better to use the .pk:
<h2>{{auction.title}}</h2>

Django HTML button on-click invoke backend function

im trying to add to my html a button that appears only on certain events, that works for me but i want to add a onclick script/function that will invoke a backend view.py function that deletes the specific room on click, the room model is : owner(fk), name, slug.
and the user model is : username password1 password2.
i just need to know how to invoke an onclick event that will call the backend function in my views.
rooms.html
{% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<button class="room-delete" id="roomDelete">Delete Room</button>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
views.py
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
from django.contrib import messages
from .models import Room, Message
#login_required
def rooms(request):
if request.method == 'POST':
room_owner = request.user
room_name = request.POST['room-name']
if not Room.objects.filter(slug = room_name).exists():
if room_name == '' or room_name.isspace() or room_name.startswith(' '):
messages.info(request, 'Invalid room name, spaces-only or string that starts with spaces is invalid.')
else:
new_room = Room(owner = room_owner,name = room_name,slug = room_name)
new_room.save()
else:
messages.info(request, 'That room already exists!, try a different name.')
rooms = Room.objects.all()
return render(request, 'room/rooms.html', {'rooms': rooms})
#login_required
def room(request, slug):
room = Room.objects.get(slug=slug)
messages = Message.objects.filter(room=room)[0:25]
return render(request, 'room/room.html', {'room': room, 'messages': messages})
#csrf_exempt
def delete_room(request): ## <<------ invoke this from html call.
print("hey")
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('', views.delete_room, name='delete_room'),
]
now i have more 2 urls.py, the project has 3 folders, 1 main (livechatapp) with settings and all, one for core htmls (core) and one for rooms html (room)
core/urls
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
path('', views.frontpage, name='frontpage'),
path('signup/', views.signup, name='signup'),
path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
and finally
livechatapp/urls
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('core.urls')),
path('rooms/', include('room.urls')),
path('admin/', admin.site.urls),
]
and this is the projects overview folders and files :
this is the project
IF you want do it in standard html:
% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<form method="POST" action="{% url 'delete_room' room.slug %}>
<button type="submit" class="room-delete">Delete Room</button></form>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
urls:
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('delete/<slug:slug>/', views.delete_room, name='delete_room'),
]
views:
#csrf_exempt
def delete_room(request,slug):
if request.method == 'POST':
try:
room = Room.objects.get(slug=slug, owner=request.user)
room.delete()
except ObjectDoesNotExist:
print('there is no room with this slug or you are not owner')
return redirect('rooms')
i advice to use csrf. allways try to use POST when manipulatind data in db.
If you want to work it without redirect you need to think of ajax call or maby htmx

Django/html issue with displaying/linking image

I'm making a site by using django. One of my models contains ImageField.
Files are saved in main_dir/media/images. I'd like to display specific images in templates but I can't achieve it. Instead of photo, I can see only default image icon which mean ( i guess ) that image is not found
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
models
class Gallery(models.Model):
name = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True, blank=True)
date_posted = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.name
class Photo(models.Model):
gallery = models.ForeignKey(Gallery, on_delete=models.CASCADE, default=None, related_name='photos')
name = models.CharField(max_length=200)
description = models.TextField(blank=False)
image = models.ImageField(blank=True, upload_to='images')
views
def gallery(request, pk):
gallery_object = Gallery.objects.get(id=pk)
context = {'gallery':gallery_object}
return render(request, 'Gallery/gallery.html', context)
html
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
<h1>Gallery: {{ gallery.name }}</h1>
{% for photo in gallery.photos.all %}
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
{% endfor %}
Go back to home page
{% endblock content %}
what should I change to display image correctly ?
you need to change the .get to .filter with the same condition to get multiple objects
because get will return 1 object only and you cant do the for loop in the template
There are a few things wrong. First of all, if you want to return multiple images then you have to use .filter() instead of .get() and if you are .get() instead of the filter then you don't have to loop over it as it is giving a single object. And the image is stored in Photos model and for that you will have to call that instead of gallery.
Here is how you can fix it:
For single object:
views function:
def gallery(request, pk):
gallery_object = Photos.objects.get(id=pk)
context = {'photo': photo_object}
return render(request, 'Gallery/gallery.html', context)
HTML template:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
<h1>Gallery: {{ photo.name }}</h1>
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
Go back to home page
{% endblock content %}
For returning multiple objects:
views function:
def gallery(request, pk):
gallery_object = Photos.objects.filter(#your query)
context = {'photos': photo_object}
return render(request, 'Gallery/gallery.html', context)
HTML:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
{% for photo in photos %}
<h1>Gallery: {{ photo.name }}</h1>
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
{% endfor %}
Go back to home page
{% endblock content %}
finally, i found an issue. I forgot about adding
urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
to my urls.py file.
lmao

Django blog not displaying images

I followed this tutorial on adding images to my django blog (tutorial link: https://www.youtube.com/watch?v=ygzGr51dbsY&list=PLCC34OHNcOtr025c1kHSPrnP18YPB-NFi&index=26)
But when I post a blog post the image doesn't get displayed
But the image gets saved in a folder
But when I go to the admin panel and click on the post I see this
when I click on the currently location I get this
This is my settings.py
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
# BASE_DIR = Path(__file__).resolve().parent.parent
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
'NAME': 'db.sqlite3',
}
}
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_FILE_DIRS = (
os.path.join(BASE_DIR, 'static')
)
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
But that guys BASE_DIR variable was different than mine.(I think cause he is using django 2 and I am using django 3)
So I hashed mine out and changed the BASE_DIR variable and removed it from the DATABASES dictionary.
My urls.py file
urlpatterns = [
path('register/', UserRegisterView.as_view(), name='register'),
path('edit_profile/', UserEditView.as_view(), name='edit_profile'),
# path('password/', auth_views.PasswordChangeView.as_view(template_name='registration/change-password.html')),
path('password/', PasswordsChangeView.as_view(template_name='registration/change-password.html'), name='change-password'),
path('password_success/', password_success, name='password-success')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
My add_post.html file
<head>
<title>Add Post...</title>
</head>
<h1>Add Blog Post...</h1>
<br/><br/>
<div class="form-group">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button class="btn btn-secondary">Post</button>
</form>
</div>
My detail_view.html file
<h1>{{ post.title }}</h1>
<small>By: {{ post.author.first_name }}
{{ post.author.last_name }} -
{{ post.post_date }}
{% if user.is_superuser or user.is_staff and post.author.id == user.id %}
(Edit) (Delete) <br/>
{% endif %}
<hr>
</small>
<img src="{{ post.header_image.url }}">
If I forgot to display the file please tell me.
Thank you.
I fond the problem. I need to add the + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) to my main urls.py

Exception Type: NoReverseMatch - Django

after researching for hours I cannot get rid of this error, I hope someone can help me.
Models:
class Puja(models.Model):
seller = models.OneToOneField(Seller, on_delete=models.CASCADE)
user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True,null=True)
title = models.CharField(max_length=100)
video = models.FileField(blank=True)
photo = models.ImageField(blank=True)
published_date = models.DateTimeField("Published: ",default=timezone.now())
bidding_end = models.DateTimeField()
starting_price = models.IntegerField(default=1)
#slug = models.SlugField(null=True)
def __str__(self):
return str(self.title)
#def get_absolute_url(self):
# return reverse('bidding_list_detail', args=[str(self.id)])
#slug time
def get_absolute_url(self):
return reverse('bidding_list_detail',args={'id': self.id})
Views:
class bidding_list(ListView):
model = Puja
template_name = 'bidding_templates/bidding_list.html'
"""return render(request= request,
template_name='bidding_templates/bidding_list.html',
context = {"Pujas": Puja.objects.all})"""
class bidding_list_detail(DetailView):
model = Puja
template_name = 'bidding_templates/bidding_list_detail.html'
urls:
path('admin/', admin.site.urls),
path("bidding_list/", bidding_list.as_view(), name="bidding_list"),
path('<int:pk>', bidding_list_detail.as_view(), name='bidding_list_detail'),
admin:
class PujaAdmin(admin.ModelAdmin):
list_display = ('seller','title','video','photo','published_date','bidding_end','starting_price')
admin.site.register(Puja,PujaAdmin)
template 1:
{% extends 'header.html' %}
{% block content %}
<h1>Pujas</h1>
{% for Puja in object_list %} <!--object_list-->
<ul>
<li> {{ Puja.title }} </li>
</ul>
{% endfor %}
{% endblock %}
template 2:
{% extends 'header.html' %}
{% block content %}
<div>
<h2>{{ object.title }}</h2>
<p>{{ object.seller }}</p>
</div>
{% endblock %}
Note that, whenever I remove <a href="{{ Puja.get_absolute_url }}"> from the first template, the objects "puja" in the model get properly displayed on the template, but I cannot access them. They normally exist on the admin panel, but not displayed on the website directly.
Thank you very much on advance and stay healthy.
edit 1: Here is the urls.py directly from the app created by django. To be more specific, I created after the project a new app called "main" in which I programmed all the project, including all the code on this question except the edit.
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
#from django.config import settings
#from django.config.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('main.urls')),
#path('', include('model.urls')),
#path('', include('blog.urls')),
#path('', include('photo.urls')),
#path('', include('video.urls')),
] # +static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I guess the problem is this line - return reverse('bidding_list_detail',args={'id': self.id}), you are passing id as a string but trying to match with int in url.Try following return reverse ('bidding_list_detail',args=[self.id])