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
Related
I have a problem while using Django. I was trying to create a learning_log web application from my book and came across this error: NoReverseMatch at /edit_entry/8/
Reverse for 'topic' with arguments '('',)' not found. 1 pattern(s) tried: ['topics/(?P<topic_id>[0-9]+)/\Z']. It said it was because of this line in my edit_entry.html file: p>{{ topic }}</p> but I checked my entire project and couldn't find the reason,
Here is my urls.py:
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
path('', views.index, name='index'),
path('topics/', views.topics, name='topics'),
path('topics/<int:topic_id>/', views.topic, name='topic'),
path('new_topic/', views.new_topic, name='new_topic'),
path('new_entry/<int:topic_id>/', views.new_entry, name='new_entry'),
path('edit_entry/<int:entry_id>/', views.edit_entry, name='edit_entry'),
]
views.py:
from django.shortcuts import render, redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
def index(request):
"""The home page for Learning Log."""
return render(request, 'learning_logs/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries':entries}
return render(request, 'learning_logs/topic.html', context)
def new_topic(request):
"""Add a new topic."""
if request.method !='POST':
form = TopicForm()
else:
form = TopicForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topics')
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
def edit_entry(request, entry_id):
"""Edit and existing entry."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method !='POST':
form = EntryForm(instance=entry)
else:
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html')
models.py:
from django.db import models
class Topic(models.Model):
"""A topic the user is learning about."""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model."""
return self.text
class Entry(models.Model):
"""Something specific about a learned topic."""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Return a string representation of the model."""
return f"{self.text[:50]}..."
forms.py:
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
base.html:
<p>
Learning Log
Topics
</p>
{% block content %}{% endblock content %}
topics.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
{{ topic }}
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
Add a new topic
{% endblock content %}
new_topic.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Add a new topic:</p>
<form action="{% url 'learning_logs:new_topic' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add topic</button>
</form>
{% endblock content %}
new_entry.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>{{ topic }}</p>
<p>Add a new entry:</p>
<form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name='submit'>Add entry</button>
</form>
{% endblock content %}
topic.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<p>
Add new entry
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
<p>
Edit entry
</p>
</li>
{% empty %}
<li>There are no entries for this topic yet.</li>
{% endfor %}
</ul>
{% endblock content %}
edit_entry.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>{{ topic }}</p>
<p>Edit entry</p>
<form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
index.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of what you've learned.</p>
{% endblock content %}
and that is literally everything I checked and I can't seem to find the error, please help me find the error and fix it.
In views.py, on the edit_entry function, pass context to the render method.
On the very last line of the edit_entry function, in the views.py file, add the context to the arguments you are passing to the returned render method.
def edit_entry(request, entry_id):
"""Edit and existing entry."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method !='POST':
form = EntryForm(instance=entry)
else:
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html')
Correct the last line as follows, by adding context. This is so can you can use the entry, topic, and form that you defined in the context in the html template.
return render(request, 'learning_logs/edit_entry.html', context)
I am using MVT in django. I am using generic CBV (listview, detailview). here are my codes
Here is model.py
from django.db import models
class Singers(models.Model):
name= models.CharField(max_length=256)
age= models.IntegerField()
gender= models.CharField(max_length=10)
class Albums(models.Model):
name= models.CharField(max_length=256)
singer=models.ForeignKey(Singers, on_delete=models.CASCADE)
view.py
from django.views import generic
from core.models import Albums, Singers
#in generic view instead of functions, we use classes
class AlbumView(generic.ListView):
model = Albums
template_name = 'index.html'
paginate_by = 10
def get_queryset(self):
return Albums.objects.all()
class DetailView(generic.DetailView):
model = Albums
template_name = 'detailview.html'
Here are urls.py
from django.urls import path
from core.views import AlbumView, DetailView
urlpatterns = [
path('album/', AlbumView.as_view()),
path('album/detail/<pk>/', DetailView.as_view())
]
Here is index.html
{% block content %}
<h2>Albums</h2>
<ul>
{% for albums in object_list %}
<li>{{ albums.name }}</li>
{% endfor %}
</ul>
{% endblock %}
here is detailview.html
{% block content %}
<h1>name: {{Albums.name}}</h1>
<p><strong>Singer: {{Albums.Singer}}</strong></p>
{% endblock %}
The detail view is not working fine. It is not fetching the respective name of the album and singer details.
Suggest me what should i do?
Try this
{% block content %}
<h1>name: {{object.name}}</h1>
<p><strong>Singer: {{object.singer.name}}</strong></p>
{% endblock %}
class DetailView(generic.DetailView):
model = Albums
template_name = 'detailview.html'
This is not working you have to get first context like this
def get_context_data(self, **kwargs):
// Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
// Add in a QuerySet of all the books
context['Album_list'] = Albums.objects.all()
return context
And you can do as well
context_object_name = 'publisher'
queryset = Publisher.objects.all()
I have been working on a search bar in django and I am close but having some issues rendering the results to the page.
Views.py
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj=self.request.GET.get('proj')
proj_list=Project.objects.filter(
Q(name__icontains=proj) | Q(projectTag__icontains=proj)
)
proj_list1=Project.objects.filter(
Q(department__icontains=proj)
)
proj_list2 = list(set(proj_list) & set(proj_list1))
return proj_list2
class SearchPageView(TemplateView):
template_name = 'searchbar.html'
search_results.html
{% extends 'main/base.html' %}
<html>
{%block content%}
<h1> Search Results </h1>
{% if proj %}
<ul>
{% for project in proj_list2%}
<li>
{{project.name}}, {{project.department}}, {{project.projectTag}}
</li>
{% endfor %}
</ul>
{% else %}
<h2>sorry, no results</h2>
{% endif %}
{%endblock%}
</html>
Whenever I search something that should definitely yield results, I get "sorry, no results."
Thank you. Please help me to understand my disconnect. The bigger aim for this is to then add different models to query from (i.e. not just search in projects, but also search by user).
You are checking the wrong variable. The collection of elements is object_list, not proj or proj_list2:
{% if object_list %}
<ul>
{% for project in object_list %}
<li>
{{project.name}}, {{project.department}}, {{project.projectTag}}
</li>
{% endfor %}
</ul>
{% else %}
<h2>sorry, no results</h2>
{% endif %}
The search is also quite odd, you only retrieve items if both the department and the name or the tag matches. We can simplify this to:
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj = self.request.GET.get('proj')
return =Project.objects.filter(
Q(name__icontains=proj) | Q(projectTag__icontains=proj),
department__icontains=proj
)
but it is odd that the department and the name for example should match. If you want to match any of the three, we can work with:
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj = self.request.GET.get('proj')
return =Project.objects.filter(
Q(name__icontains=proj) |
Q(projectTag__icontains=proj) |
Q(department__icontains=proj)
)
So i'm creating a to-do app. How do I get the html view to show the tasks? I tried to show the name of the tasks but it's blank. So far, it only shows the board name and the user who created it.
Here is my code so far:
Models.py
class Board(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name="Board")
name = models.CharField(max_length=200)
class Task(models.Model):
board = models.ForeignKey(Board, on_delete=models.CASCADE)
admin = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.CharField(max_length=300)
complete = models.BooleanField(default=False)
assigned_to = models.CharField(max_length=30)
views.py
def board_post_detail(request, board_id):
obj = get_object_or_404(Board, id=board_id)
taskobj= Task.objects.filter(board=obj)
context = {"object": obj, "tasks": taskobj}
return render(request, 'boards/board_post_detail.html', context)
board_post_detail.html
{% block content %}
<h1>{{ object.name}}</h1>
<p> {{tasks.text}}<p>
<p>Created by {{object.admin.username }}</p>
{% endblock %}
I realise that I needed to use a for loop to iterate throught the tasks.
{% block content %}
<h1>{{ object.name}}</h>
<ul>
{% for task in tasks %}
<li>{{ task.text }} is assigned to {{ task.assigned_to }}</li>
{% endfor %}
</ul>
<p>Created by {{object.admin.username }}</p>
{% endblock %}
Here is my image model, that I tied to the model Product
class Image(models.Model):
name = models.CharField(blank=True,max_length=20)
product = models.ForeignKey(Product)
image = models.ImageField(blank=True,null=True)
def __str__(self):
return self.name
Here is the view that I am using to try and display the images
def category(request, category_id):
categories = Category.objects.all()
images = Image.objects.all()
products = Product.objects.all()
try:
category = Category.objects.get(id=category_id)
except Category.DoesNotExist:
category = None;
template = loader.get_template('index.html')
context = {
'category': category,
'categories': categories,
'images': images,
'products': products
}
return HttpResponse(template.render(context,request))
and here is the html
{% for image in images %}
<img src="{{ image.url }}">
{% endfor %}
I know this definitely wouldn't work,but atleast this code displays the page instead of an error so i have been using it, can anyone please point me in the right direction to dipslay each image associated with each product.
Thank you!
You can try this:
{% for product in products%}
<p> {{product.name}} </p>
{% for simage in product.image_set.all %}
{% if simage.image%}
<img src="{{ simage.image.url }}">
{% endif %}
{% endfor %}
{% endfor %}