Firstly I am a beginner at Django but am slowly learning, I have deployed a couple of Django projects, but I have come up against a problem where I have run out of ideas on how to solve due to a lack of knowledge. I have no experience really with the frontend, I have yet to touch Boostrap (although obviously know some HTML ) or JS in detail.
I am using a HTML template to build a Photography portfolio, I have a Album view with image thumbnails which work nicely and I have a href to the list of images within that Album.
The problem is that template uses Boostrap Modal to open the list of images within the same page, this looks very nice and I want to try and keep it working but unsure how to pass my Django data (ie., the slug from the href ) through the modal.
What I have attempted is to split my gallery-detail template which takes in the listview of the Album images filter by that album, and then include that within my main Gallery template which uses my Gallery ListView to show the thumbnails. I though the modal would work this way as they would maybe technically be on the same page?
I'm just unsure, how do I pass view context into modals? Below is my relevant code which hopefully makes it easier to understand what I am trying to do
Where I am at the moment....the modal loads on same page, but no images are shown just the close X icon. If I right-click and open the URL all images open corresponding to that Album correctly but with no css or styling.
Models
name = models.CharField(max_length=200, null=True)
slug = AutoSlugField(populate_from='name')
created = models.DateTimeField()
visable = models.BooleanField(default=False)
type = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)
image = models.ForeignKey('Media', on_delete=models.CASCADE)
album_images = models.ManyToManyField('Media', related_name="album_pictures")
def __str__(self):
return str(self.name)
class Media(models.Model):
timestamp = models.DateTimeField()
image = models.ImageField(upload_to="media")
order = models.IntegerField(default=0)
visable = models.BooleanField(default=True)
categories = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)
class Meta:
verbose_name_plural = "Media"
Views. Straightforward enough.
class GalleryView(ListView):
template_name = "main/gallery.html"
model = Albums
class GalleryDetailView(ListView):
template_name = "main/gallery-detail.html"
model = Media
def get_queryset(self):
gallery = get_object_or_404(Albums, slug=self.kwargs['slug'])
print(gallery)
return Media.objects.filter(album_pictures=gallery)
Templates. Gallery.
{% extends "main/base.html" %}
{% load static %}
{% block gallery %}
{% for gallery in object_list %}
<div class="item col-xs-6 col-sm-6 col-md-4">
<figure class="overlay"> <a href="{% url 'main:gallery_detail' gallery.slug %}" data-toggle="modal" data-target="#myModal1">
<div class="text-overlay caption">
<div class="info">
<h2 class="post-title">{{ gallery.name }}</h2>
<div class="meta"> <span class="count">7 Photos</span> <span class="category">Hobby</span></div>
</div>
</div>
<img src="{{ gallery.image.image.url }}" alt="" /></a> </figure>
</div>
{% endfor %}
{% include "main/gallery-detail.html" %}
{% endblock %}
gallery-detail template
{% extends "main/base.html" %}
{% load static %}
{% block gallery %}
{% for gallery in object_list %}
<div class="item col-xs-6 col-sm-6 col-md-4">
<figure class="overlay"> <a href="{% url 'main:gallery_detail' gallery.slug %}" data-toggle="modal" data-target="#myModal1">
<div class="text-overlay caption">
<div class="info">
<h2 class="post-title">{{ gallery.name }}</h2>
<div class="meta"> <span class="count">7 Photos</span> <span class="category">Hobby</span></div>
</div>
</div>
<img src="{{ gallery.image.image.url }}" alt="" /></a> </figure>
</div>
{% endfor %}
{% include "main/gallery-detail.html" %}
{% endblock %}
Related
I am having an issue where I have categories for each product, so for my URLs, i have slugs referencing to each category. in the href on my frontpage (HTML pasted down below). I see that when I load the portion of the HTML that has the for loop applied makes it disappear. I have never run into this. Does anybody have any idea what's going on? I'll post the relevant div where this is occurring. I can post additional code if needed. Thanks
In this case, the Get covered now button is missing
Edsure\apps\core\templates\frontpage.html
{% extends 'base.html' %}
{% block content %}
{% load static %}
<div id="signup">
{% for category in menu_categories %}
<a class="btn btn-lg col-sm-12 slideanim" id="title" href="{% url 'category_detail' category.slug %}">
Get Covered Now!
</a>
{% endfor %}
<a class="btn btn-lg col-sm-12 slideanim" id="title" href="#">
Learn More!
</a>
</div>
Edsure\apps\core\views.py
from django.shortcuts import render
from apps.store.models import Product
def frontpage(request):
return render(request, 'frontpage.html')
Edsure\apps\store\views.py
from django.shortcuts import render, get_object_or_404
from .models import Product, Category
def product_detail(request,category_slug, slug):
product = get_object_or_404(Product, slug=slug)
context = {
'product': product
}
return render(request, 'product_detail.html', context)
def category_detail(request, slug):
category = get_object_or_404(category, slug=slug)
products = category.products.all()
context = {
'category': category,
'products': products
}
return render(request,'category_detail.html', context)
so, in your view you have no context named "menu_categories" but "category",try this instead:
{% for c in category %}
<a class="btn btn-lg col-sm-12 slideanim" id="title" href="{% url 'category_detail' c.slug %}">
Get Covered Now!
</a>
{% endfor %}
For the past few days I have been trying to give access to the admin user to upload multiple images/slides for every single post, one idea I had in mind was nesting a for loop inside the posts for loop that for every post, render also every image associated with it but it seem's I cant get it quite right.
class Post(models.Model):
title = models.CharField(max_length = 128)
image = models.ImageField(default = 'default.jpg', upload_to = 'post_pics')
content = models.TextField()
date_posted = models.DateTimeField(default = timezone.now)
category = models.ForeignKey(Category, on_delete = models.CASCADE)
def __str__(self):
return f"{self.title} - {self.category}"
def get_image_filename(instance, filename):
title = instance.post.title
slug = slugify(title)
return "post_images/%s-%s" % (slug, filename)
class Images(models.Model):
post = models.ForeignKey(Post, default= None, on_delete = models.CASCADE, related_name= 'Images')
image = models.ImageField( upload_to = get_image_filename, verbose_name = 'Images')
def __str__(self):
return f"imazh per {self.post}"
and my Html:
<div class="post-list-container">
{% for post in posts %}
<article class="post-container">
<div class="post-top">
> Focus on the for loop here
{% for post.Images in post.Images %}
<img src="{{ post.Images.url }}">
{% endfor %}
<div class="post-title"><h1>{{ post.title }} </h1></div>
<div class="post-images">
<img class="rounded" src="{{ post.image.url }}">
</div>
</div>
<div class="post-middle">
<div class="post-content"><p> {{ post.content }}</p> </div>
</div>
<div class="post-bottom">
<div class="post-category"><h2>{{ post.category }}</h2>
</div>
<div class="post-date_posted"><h1>{{ post.date_posted|date:"F d, Y" }}</h1>
</div>
</div>
</article>
{% endfor %}
</div>
Is there any way to render those images this way?
A Post will have a related set, which is what you refer to that reverse relationship as.
By default, django will make the relationship on a Post instance images_set because it takes your model name on the relationship & adds _set.
You can also choose your own related name by setting the related_name attribute on the FK field. (docs)
Here's an example;
class Map(models.Model):
members = models.ManyToManyField(
User,
related_name='maps',
verbose_name=_('members')
)
# Reverse relationship:
User.maps.all()
Or in python using your models;
post = Post.objects.first()
print(f"Images in post {post.title}")
for image in post.images_set.all():
print(image.url)
So without a custom related_name, your template loop would be something like;
{% for image in post.images_set.all %}
<img src="{{ image.url }}">
{% empty %}
<p>No images found</p>
{% endfor %}
I am new to Django. I have created 2 seperate views and URLs, however, when I load my development server and click on slides to open slides_detail.html, it opens sub_detail.html, at this point I have no clue what could cause that as there are no similar names which would lead to opening completely different detail page. Both slides and subcontent sits in the same HTML document, same with URLs and views. There are no errors, to show. Thanks in advance:
URLS:
path('<int:sub_id>/', views.sub_detail, name='sub_detail'),
path('<int:slides_id>/', views.slides_detail, name='slides_detail'),
Views:
# Will show specific sub content details
def sub_detail(request, sub_id):
subcontent = get_object_or_404(SubContent, pk=sub_id)
context = {
'subcontent': subcontent,
}
return render(request, 'home/sub_detail.html', context)
# Will show specific slides content details
def slides_detail(request, slides_id):
slides = Slides.objects.get(pk=slides_id)
context = {
'slides': slides,
}
return render(request, 'home/slides_detail.html', context)
HTML for slides:
{% for slides in slides %}
<div class="swiper-slide">
<div class="card">
<a href="{% url 'slides_detail' slides.id %}">
<img src="{{ slides.image.url }}" class="card-img-top img-height" alt="..."></a>
<div class="card-body bg-dark">
<h5 class="card-title text-light font-weight-bold text-center">{{ slides.title }}</h5>
</div>
</div>
</div>
{% endfor %}
HTML for subcontent:
{% for sub in subcontent %}
{% if forloop.counter|divisibleby:2 %}
<div class="row">
{% if sub.image %}
<div class="col-md-6 section-index-img">
<img src="{{ sub.image.url }}" class="rounded img-fluid" alt=""/>
</div>
{% endif %}
<div class="col-md-6">
<a href="{% url 'sub_detail' sub.id %}">
<h4>{{ sub.title }}</h4>
</a>
<p class="text-muted">{{ sub.description | linebreaks }}</p>
</div>
</div>
{% else %}
I have created 2 seperate views and URLs, however, when I load my development server and click on slides to open slides_detail.html, it opens sub_detail.html.
You did not create two separate URLs, you created the same path. Both paths will fire on the same patterns. This thus means that if you have a {% url 'slides_detail' 42 %}, for example, it will be written as /42, but this is also a valid path for the sub_detail, so when you make a request with that path, Django will "fire" the first view that matches, in this case sub_detail.
You should make the paths non-overlapping, for example:
path('sub/<int:sub_id>/', views.sub_detail, name='sub_detail'),
path('slide/<int:slides_id>/', views.slides_detail, name='slides_detail'),
I have two different models. One is for posts and other one is for images.
what I want is to display all images for every single post. Here is the file for models:
class Cars_Posts(models.Model):
user = models.ForeignKey(MyUser, on_delete=models.CASCADE)
post_city = models.ForeignKey(City, on_delete=models.CASCADE)
post_title = models.CharField(max_length=256)
post_detail = models.TextField(max_length=65536)
price = models.PositiveIntegerField()
def __str__(self):
return "%s %s %s %s %s"(
self.user.id, self.post_city,
self.post_title, self.post_detail, self.price,)
class Images_Cars(models.Model):
post = models.ForeignKey(Cars_Posts, on_delete=models.CASCADE)
car_images = models.ImageField(upload_to='car_images', blank=True, null=True )
def __str__(self):
return "%s %s " % (self.post_id, self.car_images, )
Here is the view FUNCTION FOR SEARCH (QUERY DATA BASE):
def search(request):
template = 'path/to/template.html'
# get all cities in data base
all_p_cities = City.objects.all()
#get the exact city selected by user and passed through the variable h_qc
query_c = request.GET.get('h_qc')
# get posts under the selected city
result = Cars__Posts.objects.filter(Q(post_city__city_name__iexact=query_c)
# get posts IDs of the result object
p_id=[]
for item in result:
p_id+= [item.id]
# print(p_id)
#get all images under each single post
all_images=[]
for item in p_id:
images = Images_Cars.objects.filter(post_id = item)
all_images+=[images]
# print (p_id)
# print(result)
print(all_images)
context = {
'post_city' : query_c,
'result': result,
'all_images':all_images,
}
return render(request, template, context )
both files run with no error. However in the template I want to display all posts and all images for every single post. I need your help in here. I looped over results and could get all posts. But I got also all images for every single posts repeated in every loop. So , instead of getting only images related to the current post, I got all images for all posts in current post and all subsequent posts. Any help or suggestion will be appreciated. Also any suggestion for writing the code in view file with an efficient and sophisticated way is appreciated.
Here is portion of the HTML File:
{% csrf_token %}
{% for item in result %}
<li class="result-row">
<!-- image box -->
<span>
<a href="#" class="result-image-act" >
{% for image in all_images %}
<!-- if image list is empty display the default image -->
{% if not image %}
<img src="{% static 'path/to/default image' %}" class="active">
{% endif %}
<!-- I have class ="active" which is supposed to be class of first image -->
{% if image and image.0 %}
<img class="active" src="{{image.item.car_images.url}}" >
{% elif image and not image.0 %}
<img src="{{image.item.car_images.url}}" >
{% endif %}
{% endfor %}
</a>
<span class="embed-result-price">{{item.price}}</span>
<div class="swipe-wrap">
<div class="swipe-wrap-lef">
<span class="move" >
<div class="swipe-prev">
<p><</p>
</div>
</span>
</div>
<div class="swipe-wrap-rig">
<span class="move" >
<div class="swipe-next">
<p>></p>
</div>
</span>
</div>
</div>
</span>
<span class="result-price">{{result.price}}
</span>
<span class="result-price">{{result.title}}</span>
</li>
{% endfor %}
Note: inside the html javascript code that will take care of swipe images for every single post that is why I fetch for the first image for every single post to add class="active" to it
You can do it directly in templates with reverse related name:
add a property method in your ImageCars model to check whether files are actually exist
class Images_Cars(models.Model):
''' code '''
car_images = models.ImageField(upload_to='car_images', blank=True, null=True )
#property
def car_images_exists(self):
return self.car_images.storage.exists(self.car_images.name)
templates
{% for item in result %}
{% for image in item.images_cars_set.all %}
#<!-- The images_cars instance is here -->
{% if image.car_images_exists %} # see changes in models
{{image.car_images.url}}
{% endif %}
{% empty %}
#<!--Item has no image_cars instances here: item.images_cars_set.all -->
<h3>No Images</h3>
{% endfor %}
{% endfor %}
You don't really need to loop through the queryset in views and again in templates
result as template variable is enough to have everything in templates
I have a problem using the for loop tag, It is fine for tabs but the reference for id in tab content itself is the problem as I can't access the instant value of in {{spec}} and now How can I customize my url with nav pills tabs to show the courses related to specializations,
category_page.html
<!-- This is tabs with for loop for data in specializations worked well-->
<div class="row" >
<div class="list-group col-md-4" role="navigation">
{% for specs in spec %}
<button type="button" class="list-group-item" data-toggle="tab" href="{{ specs }}">{{ specs }}</button>
{% endfor %}
</div>
<!-- Here is the tab content and it doesn't work well as I need data appears related to the tab itself -->
<div class="col-md-8">
<div class="tab-content ">
{% for specs in spec %}
<div id="{{ specs }}" class="tab-pane fade ">
<div class="row">
{% for instances in courses_spec %}
<div class="col-sm-6 col-md-6">
<div class="caption">
<h3>{{ instances.name }}</h3>
</div>
</div>
{% endfor %}
</div>
</div>
views.py
def categories_pages(request, category_name, speci_name=None):
courses = Course_dir.objects.filter(
availability=True,
id_CO__id_S__name=category_name
).order_by('date')
courses_spec = Course_dir.objects.filter(
availability=True,
id_CO__name=speci_name
).order_by('date')
spec = Specialization.objects.filter(
id_S__name__contains=category_name
).order_by('name')
context = {
"courses": courses,
"spec": spec,
"courses_spec": courses_spec
}
return render(request, 'categories/categories-page.html', context)
urls.py
url(r'^categories/(?P<category_name>[-\w]+)/$', views.categories_pages, name='category_detail'),
url(r'^categories/(?P<category_name>[-\w]+)/(?P<speci_name>[-\w]+)$', views.categories_pages, name='specialization_detail'),
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=300, blank=True)
slug = models.SlugField(default=None)
def get_absolute_url(self):
self.slug = slugify(self.name)
return reverse('category_detail', args=[str(self.slug)])
class Specialization(models.Model):
id_S = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
slug = models.SlugField(default=None)
def __str__(self):
return self.name
def get_absolute_url(self):
self.slug = slugify(self.name)
return reverse('spec_detail', args=[str(self.slug)])
A couple things -
You aren't calling get_absolute_url anywhere, so the template will only display the return value of the model's __unicode__ method (if Python 2) or __str__ method (if Python 3).
Don't call for spec in spec, use separate variables so there isn't namespace pollution and potential errors.
{% for each_spec in spec %}
<button type="button" class="list-group-item" data-toggle="tab"
href="{{ each_spec.get_absolute_url }}">{{ spec }}</button>
{% endfor %}