I want to get image form Image model for my Product model and show it cart template
This is my Code:
ecommerce/models.py
class Product(models.Model):
name = models.CharField(max_length=200)
content = models.TextField()
excerpt = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2)
status = models.IntegerField(default=0)
date = models.DateTimeField(auto_now_add=True)
quantity = models.PositiveIntegerField()
author = models.PositiveIntegerField()
featured_image = models.CharField(max_length=300)
available = models.BooleanField(default=True)
def __str__(self):
return self.name
class Image(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
image = models.ImageField()
cart/views.py
#require_POST
def cart_add(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, pk=product_id)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product,
quantity=cd['quantity'],
update_quantity=cd['update'])
return redirect('cart:cart_detail')
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={'quantity': item['quantity'],
'update': True})
return render(request, 'cart_detail.html', {'cart': cart})
cart/templates/cart.html
<tbody>
{% for item in cart %}
{% with product=item.product %}
<tr>
<td>
{% for product in products %}
<img src="{{ product.first_image.src }}" alt="" width="auto" height="340"/>
{% endfor %}
</td>
<td>{{ product.name }}</td>
.
.
.
</tr>
{% endwith %}
{% endfor %}
</tbody>
i have read this link
but it is no use to me, please help me, I am newby to this
Thank you
You should use reverse lookup image_set. To get first image do product.image_set.first.image.url:
<img src="{{ product.image_set.first.image.url }}" alt="" width="auto" height="340"/>
to get all images iterate over image_set:
{% for image in product.image_set.all %}
<img src="{{ image.src }}" alt="" width="auto" height="340"/>
{% endfor %}
Note you should remove this part:
{% for product in products %}
{% endfor %}
since you dont pass products variable into template context.
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>
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 %}
I'm making site for applications. And have two models: Applications and Guests and they have manytomany connection, because application can have 2 or more guests and 1 guest may be in many applications.
For making applications i use formset_factory with delete option. The problem is - I can't find any good examples with code for manytomanyfield and formset and I can't bound them in template. I can't display the table at all. Here's the code.
p.s. don't pay attention to cyrillic symbols
models
class Guests(models.Model):
unique_number_guest = models.IntegerField(unique=True, primary_key=True, verbose_name='№')
organisation = models.CharField(max_length=100, verbose_name='Организация', null=True)
full_name = models.CharField(max_length=100, verbose_name='ФИО')
position = models.CharField(max_length=100, verbose_name='Должность', blank=True, null=True)
chosen = models.BooleanField(default=False, verbose_name='Выбран')
class Applications(models.Model):
ntc_cabins = (
('2-5', '2-5'),
('2-10', '2-10'),
('2-12', '2-12'),
)
ntc_blocks = (
('ЦОК', 'ЦОК'),
('БМЗ', 'БМЗ')
)
unique_number_app = models.IntegerField(unique=False, null=True)
visit_date = models.DateField(default=date.today()+timedelta(days=1), verbose_name='Дата:')
visit_time = models.TimeField(default='12:00', verbose_name='Время:')
cabin = models.CharField(max_length=5, verbose_name='Кабинет:', choices=ntc_cabins, default='2-12')
block = models.CharField(max_length=10, verbose_name='Корпус:', choices=ntc_blocks, default='ЦОК')
author = models.CharField(max_length=100, verbose_name='Автор:')
guests = models.ManyToManyField(Guests)
views
def ApplicationFormation(request):
form = ApplicationsForm(request.POST)
form.guest_instanses = GuestsFormSet(request.POST)
if request.method == "POST":
if form.is_valid():
applications = Applications()
applications.cabin = form.cleaned_data['cabin']
applications.save()
for person in form.guests_visited:
guest = Guests()
guest.full_name = person['full_name']
guest.organisation = person['organisation']
guest.position = person['position']
guest.save()
applications.guests.add(guest)
return HttpResponse('good job')
print(form.errors)
else:
formset = GuestsFormSet()
print('FORMSET:', formset)
return render(request, 'myprofile/applications_form.html', {'form': form, 'fomset': formset})
forms
class GuestsForm(ModelForm):
organisation = forms.CharField()
full_name = forms.CharField()
position = forms.CharField()
class Meta:
model = Guests
exclude = ('unique_number_guest', 'chosen',)
GuestsFormSet = formset_factory(GuestsForm, extra=1, can_delete=True)
class ApplicationsForm(ModelForm):
visit_date = forms.DateField()
visit_time = forms.TimeField()
cabin = forms.CharField()
block = forms.CharField()
guests = GuestsFormSet()
class Meta:
model = Applications
exclude = ('unique_number_app', 'author', 'guests', 'ntc_cabin')
and template
{% extends "base.html" %}
{% load static %}
{% block title %}{% endblock %}
{% block content %}
<h2>Заявка на пропуск</h2>
<hr>
<div class="col-md-4">
<form action="" method="post" class="">
{% csrf_token %}
{{ form.as_p }}
<h3>Гости</h3>
<table id="table-guests">
{{ formset.management_form }}
{% for form in formset %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Сохранить и сформировать заявку"/> Назад
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'formset/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'добавить',
deleteText: 'удалить',
prefix: 'Guests'
});
</script>
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 %}
Paginator Number of Pages does not update in HTML after filtering with django_filter.
html file
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
The page_obj.paginator.num_pages is the initial number (without any filters) of all results in the table (example: I got 12 results and showing 3 results/page => 4 pages)
views
class SearchBookView(ListView):
template_name = "booksearch.html"
paginate_by = 3
model = Book
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
book_qs = Book.objects.all()
book_filter = BookFilter(self.request.GET, queryset=book_qs)
paginator = Paginator(book_filter.qs, self.paginate_by)
print(paginator.num_pages) ### Prints the correct num pages everytime even after filtering
page = self.request.GET.get('page')
try:
book_list = paginator.page(page)
except PageNotAnInteger:
book_list = paginator.page(1)
except EmptyPage:
book_list = paginator.page(paginator.num_pages)
context['book_list'] = book_list
context['book_filter'] = book_filter
return context
After adding a filter (let's say after filtering it shows 5 results) page_obj.paginator.num_pages should be 2 in my HTML, right? Although in my view in print(paginator.num_pages) it shows 2, in the HTML it stays the original 4 pages. How can I pass this to the HTML file?
EDIT
filters
class BookFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains')
author = django_filters.CharFilter(lookup_expr='icontains')
category = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Book
ields = ['name', 'author', 'category',]
full html
<h1 class="h1"> Search Books </h1>
<form method="get">
{{ book_filter.form.as_p }}
<button type="submit">Search</button>
</form>
<div class="container">
<table>
<thead>
<tr>
<th>Name</th>
<th>Author</th>
<th>Category</th>
</tr>
</thead>
<tbody>
{% for book in book_list %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.category }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li>
<span>Previous</span>
</li>
{% endif %}
<li class="">
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
</li>
{% if page_obj.has_next %}
<li>
<span>Next</span>
</li>
{% endif %}
</ul>
{% else %}
<p>No books available</p>
{% endif %}
</div>
WORKAROUND
I did a workaround but it is kind of ugly:
in my view I added a context['num_pages'] = paginator.num_pages and pass it my HTML:
<span>Page {{ page_obj.number }} of {{ num_pages }}.</span>
Any suggestions on how to do this the correct way without adding a new context key, value pair?
You should set the queryset in the get_queryset method.
def get_queryset(self):
book_qs = Book.objects.all()
self.book_filter = BookFilter(self.request.GET, queryset=book_qs)
return book_filter.qs
Django will take care of paginating the queryset, and all you need to do in get_context_data is add book_filter to the context.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['book_filter'] = self.book_filter
return context