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
Related
I want to get m2m data in my template through the views but failing to do so. The thing is that I'm able to show the data of m2m field looping it from template itself but it does slow down the website.
My Team apps Model looks like this:
class Team(models.Model):
title = models.CharField(max_length=255)
team_country = CountryField(max_length=200, blank=True, null=True)
members = models.ManyToManyField(User, related_name='teams')
created_by = models.ForeignKey(User, related_name='created_teams', on_delete=models.CASCADE)
Now in my tournament app I'm trying to get "members" of the team.
My Tournamet Views look like this:
def tournament_page(request, slug):
page = 'tournament_page'
user = request.user
tournament = Tournament.objects.get(slug=slug)
players = tournament.participants.select_related('user')
all_players = Profile.objects.select_related('user')
side_tourneys_ongoing = Tournament.objects.filter(state='Ongoing')[:10]
side_tourneys_upcoming = Tournament.objects.filter(state='Upcoming')[:10]
side_tourneys_completed = Tournament.objects.filter(state='Completed')[:10]
teams = Team.objects.select_related('created_by')
context = {
'page': page,
'tournament': tournament,
'side_tourneys_ongoing': side_tourneys_ongoing,
'side_tourneys_upcoming': side_tourneys_upcoming,
'side_tourneys_completed': side_tourneys_completed,
'teams': teams,
'players':players,
'all_players':all_players
}
Now I'm able to show the teams with their members in the template using for loop inside the template itself as:
Html template
<div class="grid-x">
{% for team in teams %}
{% for player in players %}
{% if team.id == player.active_team_id and team.game == tournament.game %}
<div class="wf-card event-team">
<div> {{team.title}} </div>
<div class="event-team-players">
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
{% endfor %}
</div>
What I want is to use this piece of code
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
in my views since it causes the website to slow down and idk why.
What I tried in my views is:
all_teams = Team.objects.all()
members = all_teams.members.all()
and
members = Team.objects.all().prefetch_related('members')
First one throws an error:
'QuerySet' object has no attribute 'members'
Second one shows lots of blank records
Tried almost everything with search but none of them helped except using the code that I provided directly in the template itself.
Edited based on comments below. You should be able to do this more simply by prefetching team members.
views.py
def tournament_page(request, slug):
page = 'tournament_page'
user = request.user
tournament = Tournament.objects.get(slug=slug)
all_players = Profile.objects.select_related('user')
side_tourneys_ongoing = Tournament.objects.filter(state='Ongoing')[:10]
side_tourneys_upcoming = Tournament.objects.filter(state='Upcoming')[:10]
side_tourneys_completed = Tournament.objects.filter(state='Completed')[:10]
teams = Team.objects.select_related('created_by').prefetch_related('members')
template.html
<div class="grid-x">
{% for team in teams %}
{% if team.game == tournament.game %}
<div class="wf-card event-team">
<div> {{team.title}} </div>
<div class="event-team-players">
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
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)
)
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'm creating a sample company web database, mainly with employee records and stuff. On one of the page, I want to display all the employees based on their department.
On my models, the department is a CharField choices. I can display the list of these departments by creating a list comprehension in views.py then forloop buttons on the html page with an href tag to the department's page. Now on this where I'm having difficulties. Clearly each element of the for loop will just get redirected to the same page no matter which button was clicked. I've tried to create a query filter and pass the actual department's name and this will work.
On my views i have this:
from django.shortcuts import render
from .models import Staff
def depts(request):
deptList = Staff.department_list
depts = [x[1] for x in deptList]
return render(request, 'dsvstaff/depts.html',{'depts':depts})
def theStaffs(request):
staffs = Staff.objects.filter(department='?')
return render(request, 'dsvstaff/theStaffs.html',{'staffs':staffs})
Then on my Department list page:
{% block content %}
<div class="container">
{% for dept in depts %}
<a class="btn btn-primary" href="{% url 'theStaffs' %}">{{ dept }}</a>
{% endfor %}
</div>
{% endblock %}
This page is where I'm having difficulties:
{% block content %}
{% for x in staffs %}
{{ x.first_name }} {{ x.last_name }} - {{ x.postion }}
{% endfor %}
{% endblock %}
What I wanted is to pass the name of the department's name in the query filter based on the button clicked.
You need to add an extra parameter to determine the departement:
def staff(request, department):
staffs = Staff.objects.filter(department=department)
return render(request, 'dsvstaff/theStaffs.html',{'staffs':staffs})
You will need to add this to the urls.py as well:
# app/urls.py
from django.urls import path
from app.views import staff
urlpatterns = [
path('staff/<department>', staff, 'staff'),
# ...
]
{% block content %}
<div class="container">
{% for dept in depts %}
<a class="btn btn-primary" href="{% url 'staff' department=dept %}">{{ dept }}</a>
{% endfor %}
</div>
{% endblock %}
It however does not look like a good idea to store the department as a CharField. Since a department is an entity, it makes sense to define a model for this, such that you can refer to it like a ForeignKey. This will reduce the database size, make it easier to maintain the database, and it is easier to change the name of a department. See more on database normalization [wiki].
I am trying to build a simple search function on django that leads me to the link when I click on it. (I know API links are JSON links so clicking on them gives you no output of value but the point is to be able to click on them)
i tried using but it doesn't work
from my results.html:
{% for dataset in datasets %}
<br/>
{{ dataset.datasets_available }}
<br/>
{{ dataset.data_source }}
<br/>
{{ dataset.brief_description_of_datasets }}
<br/>
{{ dataset.country }}
<br/>
<a href='https://www.google.com'>{{ dataset.api_documentation }}<a>
<br/> #^ is the part i wanna fix
<br/>
{% endfor %}
{% else %}
<p style="font-family:Cambria">No search results for this query</p>
{% endif %}`
from views.py:
def results(request):
query = request.GET.get('q')
if query:
datasets = api_data.objects.filter(Q(datasets_available__icontains=query))
context = {
'datasets': datasets,
}
return render(request, 'Search/results.html', context)
from models.py:
class api_data(models.Model):
data_source = models.TextField()
brief_description_of_data = models.TextField()
datasets_available = models.TextField()
brief_description_of_datasets = models.TextField()
country = models.TextField()
api_documentation = models.TextField()
class Meta:
verbose_name_plural = "api_data"
api_documentation is currently urls in strings. i want to be able to click on the output in html and view the actual website
I'm not sure what you're trying to do, but if the website URL is in the api_documentation field, then you need to make this field the href of your html anchor.
Something like this:
<a href='{{ dataset.api_documentation }}'>{{ dataset.api_documentation }}</a>