So in short, I have a ListView in Django which displays pictures with tables on the website. Then I have a DetailView where I am placing a second webpage to use with slugs but I guess my logic is wrong. I want to be able to click on a particular picture/ table and this would redirect me to another page( possible created with slug) where I can display more pictures of the same table. I have created everything so far but I am thinking my logic is wrong. You don't have to write code, just please explain what is the correct way of doing it since I am doing it for the first time.
First I created a Categories model which lists categories such as: tables, kitchens, wardrobes, bedrooms. I then created Image category where I would have title and image and so on but this was okay for one of the views but for this one I want to display multiple pictures as I mentioned and I saw some code which enabled me to have multiple images.
views.py
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tables.html'
context_object_name = 'category_images'
queryset = Images.objects.filter(category__category_title="tables")
class TablesDetailView(DetailView):
model = Images
template_name = "main/projects/tables_slug.html"
url.py
path('proekti/masi/', TableCategoryListView.as_view(), name='tables'),
path('proekti/masi/<slug:slug>', TablesDetailView.as_view(), name='table'),
models.py
class Category(models.Model):
category_title = models.CharField(
max_length=50
)
def __str__(self):
return self.category_title
class Images(models.Model):
title = models.CharField(
blank=True,
null=True,
max_length=50,
)
category_image = models.ImageField(
blank=True,
null=True,
)
category = models.ForeignKey(
Category,
on_delete=models.CASCADE)
def __str__(self):
return self.title
def __unicode__(self):
return self.title
slug = models.SlugField(
null=True,
)
def get_absolute_url(self):
return reverse("article-detail", kwargs={"slug": self.slug})
class PhotoAlbum(models.Model):
menu = models.ForeignKey(Images, on_delete=models.CASCADE)
image = models.ImageField()
order = models.IntegerField(
blank=True,
null=True,
)
def __unicode__(self):
return self.menu
class Meta:
ordering = ('order',)
I read this would help me to easily add multiple pictures.
admin.py
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
pass
class ImagesForm(forms.ModelForm):
model = Images
class Media:
js = (
'/static/js/jquery-latest.js',
'/static/js/ui.base.js',
'/static/js/ui.sortable.js',
'/static/js/menu-sort.js',
)
class PhotoAlbumInline(admin.StackedInline):
model = PhotoAlbum
admin.site.register(
Images,
inlines=[PhotoAlbumInline],
form=ImagesForm,
list_filter=('category',),
search_fields=('title',)
)
"""
/* menu-sort.js */
jQuery(function($) {
$('div.inline-group').sortable({
/*containment: 'parent',
zindex: 10, */
items: 'div.inline-related',
handle: 'h3:first',
update: function() {
$(this).find('div.inline-related').each(function(i) {
if ($(this).find('input[id$=name]').val()) {
$(this).find('input[id$=order]').val(i 1);
}
});
}
});
$('div.inline-related h3').css('cursor', 'move');
$('div.inline-related').find('input[id$=order]').parent('div').hide();
});
"""
template tables.html
{% extends 'base.html' %}
{% block page_content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/masi.css' %}">
<div >
{% for image in object_list %}
{% if forloop.counter0|divisibleby:1 %}
<div style="background-color: whitesmoke">
<a href="{{ image.get_absolute_url }}"><img src="{{ image.category_image.url }}" alt="pic"></a>
<p>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock %}
template tables_slug.html --> where I would want to display all the images of a particular table with it doesn't show me one of the tables and doesn't show all the images I have uploaded in the admin page.
{% extends 'base.html' %}
{% block page_content %}
{% for image in category_images %}
<div>
<h2>{{ object.title }} </h2>
<img src="{{ object.category_image.url }}" alt="pic">
</div>
{% endfor %}
{% endblock %}
CodePudding user response:
Thanks for your answer.I just solved the problem I believe with simpler code. I was missing "related_names" in the model for the relation.
models.py
class PhotoAlbum(models.Model):
menu = models.ForeignKey(
Images,
on_delete=models.CASCADE,
related_name="child_images",
)
image = models.ImageField()
order = models.IntegerField(
blank=True,
null=True,
)
def __unicode__(self):
return self.menu
class Meta:
ordering = ('order',)
and for the template then: tables_slug.html
{% extends 'base.html' %}
{% block page_content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/masi.css' %}">
{% for image in image.child_images.all %}
<div >
<p>
<img src="{{ image.image.url }}" alt="pic">
</p>
</div>
{% endfor %}
{% endblock %}
CodePudding user response:
Updated
You can do this:
In your TableCategoryListView, override the get_context_data like so:
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tables.html'
context_object_name = 'category_images'
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tablesdetail.html'
context_object_name = 'detail_cat_img'
def get_context_data(self, **kwargs):
context = super(TableCategoryListView, self).get_context_data(**kwargs)
context['detail_category'] = Images.objects.all() # this gives you all the items from the Images model
context['xtr_images'] = PhotoAlbum.objects.all() # the logic to render only those photos related to the current view goes here. You have to figure this out yourself
return context # this returns the two objects above xtr_images and detailcategory
You can use the slice operator to determine number of images to show per page either in your views or on the template itself like so:
Entry.objects.all()[:5] # prints four images
This should do the trick.