Django access intermediate fields in template - django

I have django models like this:
class FittingBag(models.Model):
...
fittings = models.ManyToManyField("app.Fitting", through="FittingInBagInstances")
class FittingInBagInstances(models.Model):
fitting = models.ForeignKey("app.Fitting", on_delete=models.CASCADE)
bag = models.ForeignKey("app.FittingBags", on_delete=models.CASCADE)
qty = models.DecimalField(verbose_name='Quantity' );
Is there any way to access intermediate fields (like "qty" ) from Django template without preparing the date in the view?

You can simply iterate over the releverse relation that is constructed by the many-to-many intermediate model:
{% for fittingbag in fittingbags %}
Rendering the fittingbag: {{ fittingbag }}
{% for fittinginbag in fittingbag.fittinginbaginstances_set.all %}
qty: {{ fittinginbag.qty }}
fitting: {{ fittinginbag.fitting }}
{% endfor %}
{% endfor %}

Related

Receiving a list of related models from the list of objects (bound by a foreign key). Django

I have two very simple classes for products and photos. I would like to present products on the main page of my store along with photos related to a foreign key. But I do not know how to do this, I found many answers to get this in the view using a join like 'prefetch_related' but my ID changes for each case. So how do you present your photos for each product? are there any Django tags about which I do not know?
my models.py
class Product(models.Model)
name = models.CharField(max_length=10)
class Image(models.Model)
image = models.ImageField()
name_related = models.ForeignKay(Product, on_delate=models.CASCADE)
views.py
def home(request):
product_list = Product.objects.all()[:12]
#img = ??
context = {'product_list': product_list,
}
return render(request, 'home.html', context)
home.html
{% for product in product_list %}
{{ product.name }}
<!-- {{ product.imge }} ' element presenting the first photo for each 'product' model'???-->
{% endfor %}
Any help will be appreciated.
Since a foreign relation has been established you can iterate through the related models from the parent model.
The related models are already accessible from the parent model without doing anything explicit.
In your template you can do this:
{% for product in product_list %}
{{ product.name }}
{% for product_image in product.image.all %}
<!-- Iterate through this products related images -->
{{ product_image.image.url }}
{% endfor %}
{% endfor %}
For performance reasons, you will want to prefetch the relations, or else for every product you will do an additional query, so, in your view you will want to add this:
product_list = Product.objects.all().prefetch_related('image')[:12]
Just do
{% for product in product_list %}
{{ product.name }}
{% for image in product.image.all %}
<!-- {{ image.image.url }} -->?
{% endfor %}
{% endfor %}

Django templates iterate model fields with indices

I have the follow model:
class UserProfile(...):
...
photo1 = models.URLField()
photo2 = models.URLField()
photo3 = models.URLField()
photo4 = models.URLField()
photo5 = models.URLField()
And in the Create/Update template, I have to write five copies of the following div for file1 to file5:
<div>
Photo 1:
{% if userProfileForm.instance.file1 %}
<a href="{{ userProfileForm.instance.file1 }}" target=_blank>View</a>
{% endif %}
<input type=file name=file1>
{% if userProfileForm.instance.file1 %}
Delete
{% endif %}
</div>
Is there a way to iterate field file<i>?
{% for i in '12345' %}
<div>
Photo {{ forloop.counter }}:
...
</div>
{% endfor %}
in django you have _meta API. So I think this solves your problem if you use get_fields method (and maybe you will filter desired fields out).
hope it helps.
update with example
let me show how you should solve your problem:
desired_fields = []
for field in UserProfile._meta.get_fields()
if "photo" in field.name:
desired_fields.append(field.name)
context.update(fields=desired_fields) # pass it in the context
at this point you have your desired fields which should be used with for loop in the template. And one more thing, you would need to add some template tag to get real field from string representation:
# custom template tag
def from_string_to_field(instance, field_str):
return getattr(instance, field_str, None)
and in the template code will look like this
{% for field in fields %}
{{userProfileForm.instance|from_string_to_field:"field"}}
{% endfor %}

Django: Filter foreignkey objects by default on model

I have 3 models what create a data hierarchy: Brand, Family, Car. In displaying the DetailView for the Brand, I have a table with a Brand's families (foreignkey) and in that table, I then have a property for num_cars to display the number of cars with a foreignkey back to that family.
Example:
Brand:Ford
Families:
Taurus 150
F150 100
F250 0
This is displayed in my template as:
{% for family in brand.families.all %}
{{ family }} {{ family.num_cars }}
{% endfor %}
Is there a way to filter the families by the number of cars so I don't see results where there are 0 cars? I can do this in the template with:
{% for family in brand.families.all %}
{% if family.num_cars > 0 %}
{{ family }} {{ family.num_cars }}
{% endif %}
{% endfor %}
However that doesn't seem like the ideal solution. I'd like to have this in my models (if possible). Any ideas?
You can achieve this kind of behavour with custom managers in Django.
https://docs.djangoproject.com/en/1.10/topics/db/managers/
for example
class FamilyWithCarManager(models.Manager):
def get_query_set(self):
return super(FamilyWithCarManager, self).get_query_set().filter(num_cars__gte=0)
and then in your Family model:
class Family(models.Model):
name = models.CharField(max_length=50)
with_cars = FamilyWithCarManager()
then you should be able to write a query like this:
Family.with_cars.all()
You can add a method get_families to your model Brand
class Brand(models.Model):
title = models.CharField()
def get_families(self):
return self.families.filter(num_cars__gt = 0)
And then do something like this in your views.
{% for family in brand.get_families %}
{{ family }} {{ family.num_cars }}
{% endfor %}

Get aggregate in a template

I have this Django model:
class Location(models.Model):
name = models.CharField(primary_key=True, max_length=100)
customer = models.OneToOneField(Customer, default=None)
class Customer(models.Model):
name = models.CharField(primary_key=True, max_length=100)
class Order(models.Model):
amount = models.PositiveIntegerField(default=0)
customer = models.ForeignKey(Customer, default=0)
in my view I get them like this:
locations = models.Location.objects.all()
and the template lists them like this:
{% for location in locations %}
{{ location.customer.name }}
{% endfor %}
I would like to add a sum of all amount of all Orders connected that customer, something like:
{% for location in locations %}
{{ location.customer.name }} ordered {{ location.customer.orders.sum(amount) }} items
{% endfor %}
And according to this question, I should do that in the view, but how?
You should use .annotate (look in docs):
from django.db.models import Count
customers = models.Customer.objects.annotate(orders_count=Count('order'))
Then in templates you can use it like this:
{% for customer in customers %}
{{ customer.name }} ordered {{ customer.orders_count }} items
{% endfor %}
After some folling around I found this works:
locations = models.Location.objects.annotate(num_order=Count('customer__order'))
and then use this in the template:
{% for location in locations %}
{{ location.customer.name }} ordered {{ location.num_order }} items
{% endfor %}

Iterate set in template

I have this models:
class House(models.Model):
name = models.CharField()
class BedRoom(models.Model):
name = models.CharField()
class Catalog(models.Model):
name = models.CharField()
house = models.ForeignKey(House)
bedroom = models.ForeignKey(BedRoom)
at admin.py Catalog is inline to House
class CatalogInline(admin.TabularInline):
model = Catalog
class HomeAdmin(admin.ModelAdmin):
inline = [CatalogInline]
then I need obtain at view the list of Bedrooms from House Catalog, at Home model I have:
def bedrooms(self):
return self.catalog_set.all()
but when I do at template obtaining "houses" from a view:
{% for house in houses %}
{% for h in house %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}
I get an error:
'Catalog' object is not iterable
what I'm doing wrong?
I should define the model in a different way?
As I mentioned, you don't seem to actually be calling the bedrooms method. I guess (and it is just a guess) you mean this:
{% for house in houses %}
{% for h in house.bedrooms %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}
The bedrooms method is pointless though, as you can just as easily do this:
{% for house in houses %}
{% for h in house.catalog_set.all %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}