How to display ForeignKey object in ListView - Django - django

I have read up on this but I can't find something which solves my issue.
I am trying to display a table with a list of products with thumbnails.
The thumbnail field in the table returns no url, but returns a broken image link only for the products which own a thumbnail.
This list of products uses a ListView, and I can display the thumbnail fine in the detail view of the product (a DetailView) which uses the same template code
What do I need to do to display the thumbnail for each product in the ListView... ie. how must I change my queryset to pass the thumbnail into the template along with the product?
View
class ProductView(generic.ListView):
template_name = 'product/product.html'
context_object_name = 'product_list'
def get_queryset(self):
return Product.objects.all()
Template
{% for product in product_list %}
<tr>
<td>{{ product.title }}</td>
<td> {% if product.thumbnails.all %}
<img src="{{ product.thumbnail.url }}" alt="...">
{% endif %}
</td>
<td>{{ product.category }}</td>
<td>{{ product.subcategory }}</td>
<td>{{ product.status }}</td>
<td>{{ product.date_added }}</td>
{% endfor %}
Model
class ProductThumbnail(models.Model):
product = models.ForeignKey(Product, default=None, related_name='thumbnails')
thumbnail = models.ImageField(upload_to='thumbnails/',
verbose_name='thumbnail', blank=True,)
Please let me know if any more information is needed.

{% if product.thumbnails.all %} should be {% if product.thumbnail %}
{% if product.thumbnails.all %} would only make sense if product.thumbnails was a reverse relation
EDIT: I misread the question
You need to loop through the thumbnails {% for thumbnail in product.thumbnails.all %}

If you have only one thumbnail per Product, you should add the field
thumbnail = models.ImageField(upload_to='thumbnails/',
verbose_name='thumbnail', blank=True)
directly to the model Product and ditch the ProductThumbnail model. The way you designed your DB makes possible to have more thumbnails for each product (one-to-many relationship), but this makes your code needlessly complex.
If thumbnail was a field of the Product model, you could do simply:
{% if product.thumbnail %}
<img src="{{ product.thumbnail.url }}" alt="...">
{% endif %}

Related

Django_Filters :no need to show all items using object.all() at the first load

I am new for Django_Filter
As I notice, django_filter always loads all objects on the firs loading despite not filtered yet. Due to a large amount of data in the table in the database. So it results in poor performance for loading all objects unnecessarily.
it is rather unreasonable in my view. Thus the better way, it should filter a result whenever click button only.
How to set Django_Filter in order to show the result when only click the search button(I don't want to list all items by using objects.all()).
These are my code related to this problem
model.py
from django.db import models
class Product_Type(models.Model):
productype_name=models.CharField(max_length=100)
class Inventory(models.Model):
serial_number=models.CharField('Serial Number',max_length=50)
product_type=models.ForeignKey( Product_Type,on_delete=models.CASCADE,verbose_name='Product Type')
filter.py
import django_filters
from django_filters import *
from app.models import *
class InventoriesForCopy_Filter(django_filters.FilterSet):
class Meta:
model=Inventory
fields=['product_type','serial_number']
views.py
def list_inventory_for_copy(request, proj_id):
inventories_all = Inventory.objects.all()
xfilter = InventoriesForCopy_Filter(request.GET, queryset=inventories_all)
inventories = xfilter.qs
context = {'project_id': proj_id, 'xfilter': xfilter, 'inventories': inventories}
return render(request, 'app/inventory_add_copy.html', context)
inventory_add_copy.html
{% extends "app/layout.html" %}
{% block content %}
{% if messages %}
<ul>
{% for message in messages %}
<li><strong>{{ message }}</strong></li>
{% endfor %}
</ul>
{% endif %}
<form method="get">
{{xfilter.form}}
<button type="submit">Get Inventories</button>
</form>
Create Inventory for Project ID : {{ project_id }}
<table>
<tr>
<td>SerialNo</td>
<td>ProductType</td>
</tr>
{% for item in inventories %}
<tr>
<td>{{ item.serial_number }}</td>
<td>{{ item.product_type }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
The picture below describes itself:

Django ,How to show image on the board in templates?

I want to use like this
I'm making a bulltein board like the image.
I can show image in detail page. But i can't show image bulletin board list(index page).
How do I add images to the bulletin board list?
toy/models.py
class NewBornProduct(models.Model):
type = models.ForeignKey(Type,on_delete=models.PROTECT)
name = models.CharField(,max_length=30)
content = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
price = models.IntegerField(null=False)
class NewBornProductImage(models.Model):
product = models.ForeignKey(NewBornProduct,on_delete=models.CASCADE)
image = models.ImageField(upload_to="newborn/%Y/%m/%d")
def delete(self, using=None, keep_parents=False):
self.image.delete()
return models.Model.delete(self, using=using, keep_parents=keep_parents)
toy/views.py
def newborn(request):
obj = NewBornProduct.objects.all()
return render(request,'toy/newborn.html',{'obj':obj})
toy/newborn.html
{% for post in obj %}
<tr>
<th>{{post.id}}</th>
<th> i want to show image here!</th> <-------- Here!
<th>
{{post.name}}
</th>
<th>{{post.price}}</th>
<th>{{post.amount}}</th>
<th>{{post.pub_date}}</th>
</tr>
{% endfor %}
I do not know how to call the image because the other is fine
Do you have any ideas?
If what yoy want is "the first image if there's one":
{% for post in obj %}
<tr>
<th>{{post.id}}</th>
<th>
{% with post.newbornproductimage_set.first as img %}
{% if img %}<img src="{{ img.image.url }}" />{% endif %}
{% endwith %}
</th>
<th>
{{post.name}}
</th>
<th>{{post.price}}</th>
<th>{{post.amount}}</th>
<th>{{post.pub_date}}</th>
</tr>
{% endfor %}
Also note that:
1/ your markup is wrong, you should be using td, not th (th is a table header)
2/ naming your products queryset obj and products instances post is not going to help wrt/ readabilty/maintainability. You should rename obj to products (plural, denotes a collection) and post to product.

Can't render attributes of an objecte linked with M2M field

Trying to render attributes of objects that are linked with another object via m2m field.
#models
class Arm(models.Model):
cmrs = models.ManyToManyField(CMR, null=True)
class CMR(models.Model):
client = models.ForeignKey('Client', on_delete=models.CASCADE,
null=True, default="", blank=True)
The view
if us.groups.filter(name__in = ['prime']):
query_set = Plan.objects.order_by('-pk')
query_ys = Arm.objects.filter(date=ys)
query_rn = Arm.objects.filter(date=rn)
query_tm = Arm.objects.filter(date=tm)
client_rn = query_rn.prefetch_related('cmrs')
args = {'query_rn': query_rn,
'cl_rn': client_rn,
'query_tm': query_tm,
'query_ys': query_ys,
'query_set': query_set
}
return render(request, 'personnel/schedule/test-schedule-full.html', args)
And the template
<tbody id="add">
{% for query in query_rn %}
<tr class="row100 body {{ query.status }}" data-href="/personnel/arm/{{ query.id }}">
<td class="cell100 column1">{{ query.driver }}</td>
<td class="cell100 column2">{% for idem in cl_rn.cmrs.all %} {{ idem.client }} {% endfor %}</td>
<td class="cell100 column3">{{ query.des_from}}</td>
<td class="cell100 columnarrow"><i class="fas fa-arrow-circle-right"></i></td>
<td class="cell100 column4">{{ query.des_to }}</td>
</tr>
{% endfor %}
</tbody>
What I am trying to do is to show all the values of the client field of an CMR objects that are linked with Arm in <td class="cell100 column2"></td> but it shows nothing instead.
It doesn't make sense to have separate querysets for the prefetch_related call. You're iterating through query_rn, you need to define the prefetch_related on that same queryset and then iterate through the related objects from there; you don't need client_rn at all. So:
query_rn = Arm.objects.filter(date=rn).prefetch_related('cmrs')
...
{% for query in query_rn %}
{% for idem in query.cmrs.all %} {{ idem.client }} {% endfor %}
{% endfor %}
Note also, the first line of your code is a bit off. You shouldn't use __in with a single-list element, just check for equality; and since you just want to check that the related group exists, you should use the exists() method, which is slightly more efficient:
if us.groups.filter(name='prime').exists():

django Ordering a field with user signed in

I am a newbee in Django, And I am trying to alter one of my view to order by the user signed in. For example, If 'test#example.com' is signed in, then the Tview should give data related to Test#example.com in the first row. At the moment it is in no specific order.
Current order: for a user signed as test#example.com
GEL_TEACT trea#example.com
TREAT_ACT test#example.com
I want to order this as:
Product OWNER
TREAT_ACT test#example.com
GEL_TEACT trea#example.com
my View:
class PListView(ListView):
model = Product
template_name = "app/product_list.html"
project_list_view = PListView.as_view()
my template:
<tbody>
{% for product in object_list %}
<tr>
<td>{{ product.title }}</td>
<td>
<a href="{% url "product-update" project_id=project.pk %}">
<i class="fi-pencil"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
Thanks for your time.
These are three different options, depending on what you need. Just use one of them.
In your example, a logged in user should be displayed first. That is just one item to put in front of the list. So its easiest to do that right in the template
<ul>
<li>{{ user.username }}</a></li>
{% for item in users %}
{% if item != user %}
<li>{{ item.username }}</a></li>
{% endif %}
{% endfor %}
</ul>
However, if you want to get the list in a particular order, there are two ways to achieve that. If the order is just for this one ListView, then use the get_queryset() method of ListView()
class PListView(ListView):
model = Product
template_name = "app/product_list.html"
get_queryset(self):
return Product.objects.all().order_by('name')
However, if the data should always be ordered in this way, on all lists of the Product model, you can order it right on the model instead
class Product(models.Model):
name = models.CharField(max_length=50)
class Meta:
ordering = ['name', ]

Filtering user and showing his informations- django

i need some help in following situation.
After a successful searching for a user, i want to show the users information. It's a m2m flied, but I'm getting all objects from this model.
I do not know, how to filter users information.
Got this template:
{% for player in players %}
<tr>
<td>{{ player.last_name }} <span class="text-muted">({{ player.first_name }})</span></td>
<td>{{ player.gender }}</td>
<td>
{% for choice in search.league %}
<div class="">
{{ choice }}
</div>
{% endfor %}
</td>
This way it is showing all objects in League.
The field league is a M2M field from player.
I have this in my forms.Form
league = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple, queryset=League.objects.all())
I realize that I must also send the users-information from the view, but I do not know how.
Thanks for helping.
I would say that you want to use something like {% for choice in player.league.all %} in your template and use it in your for-loop. You can find more information about this here: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.related_name