how to use Exists and OuterRef in prefetch_related in Django? - python

I have 3 models and I need to display the area and need items only if there is at least 1 product connected. If there are no products in particular Area and Need models then it should not appear in my HTML file.
I have checked the documentation and several answers related to this topic but I cannot implement it in my script.
I also tried to create my custom filter so I can apply it directly in my template but nothing worked.
My problem is that I am getting the list of all items from Need model and I don't know how to exclude empty items from HTML page.
I will appreciate any help.
models.py
class Area(models.Model):
title = models.CharField(max_length=75, blank=False)
body = models.CharField(max_length=150, default='-', blank=False)
publish = models.DateTimeField('publish', default=timezone.now)
class Need(models.Model):
title = models.CharField(max_length=75, blank=False, null=False, help_text='max 75 characters')
body = models.CharField(max_length=150, default='-', blank=False)
publish = models.DateTimeField(default=timezone.now)
need_area = models.ForeignKey(Area, on_delete=models.CASCADE, related_name='need_area')
class ProductCategory(models.Model):
title = models.CharField(max_length=400, blank=False, null=False, help_text='max 400 characters')
body = models.TextField(default='-')
publish = models.DateTimeField('publish', default=timezone.now)
category_area = models.ForeignKey(Area, on_delete=models.CASCADE, related_name='category_area', null=True)
category_need = models.ForeignKey(Need, on_delete=models.CASCADE, related_name='category_need', null=True)
class Product(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=400, blank=False)
category = models.ForeignKey(ProductCategory, on_delete = models.CASCADE, blank=True, related_name='products')
status = models.IntegerField(choices=STATUS, default=0)
def get_absolute_url(self):
return reverse("product", kwargs={'slug': self.slug})
views.py
class Search(ListView):
template_name = 'search.html'
model = Product
queryset = Product.objects.filter(status=1)
def get_context_data(self, **kwargs):
context = super(Search, self).get_context_data(**kwargs)
filter_need = Area.objects.filter(Exists(Need.objects.filter(need_area=OuterRef('pk'))))
areas = Area.objects.prefetch_related(Prefetch('need_area', queryset=filter_need, to_attr='need_area__category_need__product')).filter(need_area__category_need__product__status=1).distinct()
context['areas'] = areas
return context
search.html
{% if areas %}
{% for area in areas %}
<div class="border mb-4 pb-4 px-2">
<h2 class="fw-bold my-2">{{area.title}}</h2>
{% for need in area.need_area.all %}
<h4 class="text-muted mt-4">{{need.title}}:</h4>
{% for product_category in need.category_need.all %}
{% for product in product_category.product.all %}
<span class="rounded-pill bg-hubble text-dark f-12 p-2">{{product.title}}</span>
{% endfor %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
{% endif %}

Related

how do I render shipping address_one object associated with a specific order

So the customer has an order page where I want to render their order details, specifically product name, date ordered, status, and their delivery location, right now I got everything to work except the delivery location("address_one"). I would really appreciate it if someone can help, thx!
models.py
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
class Product(models.Model):
name = models.CharField(max_length=150)
description = models.TextField()
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
address_one = models.CharField(max_length=200)
views.py
#login_required
def orders(request):
orderitems = OrderItem.objects.filter(order__customer__user=request.user)
#how do I get the shipping address associated with order
shipping = ShippingAddress.objects.filter()
context = {"orderitems": orderitems, "shipping": shipping}
HTML
{% for orderitem in orderitems %}
<div class="order-data-view">
<div class="order">{{ orderitem.product.name }}</div>
<div class="date">{{ orderitem.date_added }}</div>
<div class="status">dummydata</div>
<div class="delivering-to">{{ shipping.address_one }}</div>
</div>
{% endfor %}
Try this:
views.py
#login_required
def orders(request):
orderitems = OrderItem.objects.filter(order__customer__user=request.user).prefetch_related('order__shippingaddress_set')
context = {"orderitems": orderitems}
html(template)
{% for orderitem in orderitems %}
<div class="order-data-view">
<div class="order">{{ orderitem.product.name }}</div>
<div class="date">{{ orderitem.date_added }}</div>
<div class="status">dummydata</div>
<div class="delivering-to">{{ orderitem.order.shippingaddress_set.all.0.address_one }}</div>
</div>
{% endfor %}

OperationalError at /1 no such column: auctions_comment.listing_id

I'm new to Django. i'm trying to display all the comments for a listing in an auction site
Help me find a way to display all the comments for a listing.
Mosdels.py
class Listing(models.Model):
title = models.CharField(max_length=64, default="")
starting_bid = models.CharField(max_length=64, default="$")
description = models.TextField(default="")
image_url = models.CharField(max_length=200, default="")
date = models.DateTimeField(default=timezone.now)
category = models.ForeignKey(Category, on_delete=models.CASCADE, default="")
def __str__(self):
return self.title
class Comment(models.Model):
comment = models.TextField(default="")
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="comments", default="")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="comments", default="")
def __str__(self):
return f"{self.user} - {self.listing}"
views.py
def listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
comments = listing.comments.all()
return render(request, "auctions/listing.html", {
"listing":listing,
"comments":comments
})
_If you are trying to display in a template you can use something like following:
{% for listing_item in listing %}
<div>{{listing_item.title}}
{% for comment in listing_item.comment_set.all %}
<div>{{comment}}</div>
{% endfor %}
</div>
{% endfor %}
EDIT: If only sending the one listing from your view:
{{listing.title}}
{% for comment in listing.comment_set.all %}
<div>{{comment}}</div>
{% endfor %}
EDIT2: Noticed you have a related name there.
{{listing.title}}
{% for comment in listing.comments.all %}
<div>{{comment}}</div>
{% endfor %}

Django template return all files in section

Here my problem, The user can add Sections, in the section he can add documents, what I would like to do it's to return all documents added in section I can't figure it out which way is the best to filter by section:
Here my model for the Documents :
class Document(models.Model):
"""
Staff of the hospital center services
"""
# ATTRIBUTES
label = models.CharField(
max_length=255,
verbose_name='Intitulé'
)
description = models.TextField(
verbose_name='Description',
blank=True,
null=True
)
document = models.FileField(
verbose_name='Document'
)
section = models.ForeignKey(
'espace_documentaire.EspaceDocumentaire',
verbose_name="Espace Documentaire",
related_name="documents",
null=True,
blank=True,
on_delete=models.CASCADE
)
dedicated_page = models.ForeignKey(
"pages.Pages",
verbose_name="Page",
related_name="documents",
null=True,
blank=True,
on_delete=models.CASCADE
)
division = models.ForeignKey(
"services.Division",
verbose_name="Pôle",
related_name="documents",
null=True,
blank=True,
on_delete=models.CASCADE
)
order = models.IntegerField(
verbose_name="Ordre d'affichage",
default=0
)
# TRACE
date_created = models.DateTimeField(
verbose_name="date de création",
auto_now=True
)
date_updated = models.DateTimeField(
verbose_name="date de modification",
auto_now=True
)
def __str__(self):
return self.section
Here my Model for the Sections :
class EspaceDocumentaire(models.Model):
# ATTRIBUTES
section = models.CharField(
max_length=255,
verbose_name='Nom de la section'
)
colorsection = models.CharField(
max_length=255,
verbose_name='Couleur de la section'
)
order = models.IntegerField(
verbose_name="Ordre d'affichage",
default=0
)
document = models.ForeignKey(
'documents.Document',
verbose_name="Document",
related_name="documents",
null=True,
blank=True,
on_delete=models.CASCADE
)
def __str__(self):
return self.section
Here my template :
{% for ed in espace_documentaire %}
<div class="dpt-toggle" id="{{ ed.pk }}">
<h3 class="toggle-title">{{ed.section}}</h3>
<div class="toggle-content">
<div class="tabs clearfix">
{% for document in documents %}
{% if document.section == ed.section %}
<h1>{{ document.label }}</h1>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endfor %}
Thanks
Here is how you would filter a single section documents in a view:
def section_documents(request, pk):
section = EspaceDocumentaire.objects.get(pk=pk)
documents = section.documents.all() # using related name you set in your model
return render(request, 'section_documents.html', {'section': section, 'documents': documents})
Then in your template:
{% for document in documents %}
{{ document }}
{% endfor %}
OR you could also just use the related name in the template like this:
def sections_and_documents(request):
sections = EspaceDocumentaire.objects.all()
return render(request, 'sections_and_documents.html', {'sections': sections)
and in the template:
{% for section in sections %}
{{ section }}
{% for document in section.documents.all %}
{{ document }}
{% endfor %}
{% endfor %}

Template Variations title not showing

I have made a variation to an Item class in models.py and I think i got the template syntax right but apparently there are something wrong which i can't figure it out
Here is the model
class Item(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
price = models.FloatField()
slug = models.SlugField(unique=True)
image = models.ImageField(blank=False, upload_to='approved designs')
def __str__(self):
return self.title
class Meta:
unique_together = ('title', 'slug')
class Variation(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
title = models.CharField(max_length=120)
image = models.ImageField(null=True, blank=True)
price = models.FloatField(null=True, blank=True)
def __str__(self):
return self.title
and here is the template
{% if item.variation_set.all %}
<select class='form-control' name='size'>
{% for items in item.variation_set.all %}
<option value='{item.variation|lower}'>{{title.title|capfirst}}</option>
{% endfor %}
</select>
{% endif %}
you may want to try items.title with the 's'

Having trouble writing loops in django template

Hello guys I am currently working on django views and templates and met some problems.
I have a model named 'metabolites', which contains: id, name, compartment, charge and formula 5 components.
I have another model named 'Reactionsmeta', which contains: id(reactions), name, metabolie1, metabolite2, .... metabolite6. The table of this model is not filled complete, because sometimes one id corresponds to 5 metabolites, but sometimes even 20.
I write a template which can displays all the reaction, when I click on the reaction and enter the detail page, I also want to display the metabolites that involve in this reactions. My views.py and templates are written as below:
reactions_detail.html
{% extends 'Recon/Base.html' %}
{% load static %}
{% block title %}Reaction Details{% endblock %}
{% block body %}
<h1>{{ reactionsmeta.id }}</h1>
<h2>{{ reactionsmeta.name}}</h2>
<!-- Left Album Info -->
<div class="col-sm-4 col-md-3">
<div class="panel panel-default">
<div class="panel-body">
<a href="{% url 'detail_reaction' reactionsmeta.id %}">
{% if reactionsmeta.id %}
<img src="{% static "Recon/images/Logo-Technische-Universiteit-Eindhoven.jpg" %}" class="img-responsive">
{% else %}
<h3>No image to display</h3>
{% endif %}
</a>
<h1>{{ reactionsmeta.id }} <small>{{ reactionsmeta.name }}</small></h1>
</div>
</div>
</div>
views.py
from django.views import generic
from .models import Reactionsmeta,Metabolites,Reactions
from django.shortcuts import render
class IndexView(generic.ListView):
template_name = 'Recon/index.html'
context_object_name = 'Reactions_object'
def get_queryset(self):
return Reactionsmeta.objects.all()
class DetailsView(generic.DetailView):
model = Reactionsmeta
template_name = 'Recon/reactions_detail.html'
def get_context_data(self, **kwargs):
context = super(DetailsView, self).get_context_data(**kwargs)
context['metabolite'] = Metabolites.objects.all()
context['reactions'] = Reactions.objects.all()
# And so on for more models
return context
How can I write the loop in reaction_detail.html???
EDIT:
class Metabolites(models.Model):
id = models.CharField(primary_key=True, max_length=255)
name = models.CharField(max_length=255, blank=True, null=True)
compartment = models.CharField(max_length=255, blank=True, null=True)
charge = models.CharField(max_length=255, blank=True, null=True)
formula = models.CharField(max_length=255, blank=True, null=True)
notes = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'Metabolites'
class Reactionsmeta(models.Model):
id = models.CharField(primary_key=True, max_length=255)
name = models.CharField(max_length=255, blank=True, null=True)
metabolite1 = models.ForeignKey('Metabolites', db_column='metabolite1',
blank=True, null=True, on_delete=models.CASCADE)
stoichiometry1 = models.IntegerField(blank=True, null=True)
metabolite2 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry2 = models.IntegerField(blank=True, null=True)
metabolite3 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry3 = models.CharField(max_length=255, blank=True, null=True)
......
stoichiometry55 = models.CharField(max_length=255, blank=True, null=True)
metabolite56 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry56 = models.CharField(max_length=255, blank=True, null=True)
metabolite57 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry57 = models.CharField(max_length=255, blank=True, null=True)
metabolite58 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry58 = models.CharField(max_length=255, blank=True, null=True)
metabolite59 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry59 = models.CharField(max_length=255, blank=True, null=True)
metabolite60 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry60 = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'ReactionsMeta'
I don't see a great way to do this since each metabolite has its own field and isn't necessarily a foreign key. It'd be easier if the metabolite were in a ManyToMany field with through defining the stoichiometry.
Django's ManyToMany Relationship with Additional Fields
https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_many/
That said, in the template you can display a Reactionsmeta metabolite1 and stoichiometry one by :
{% if reactionsmeta.metabolite1 %}
Metabolite: {% reactionsmeta.metabolite1 %}
Stoichiometry: {% reactionsmeta.stoichiometry1 %}
{% endif %}
{% if reactionsmeta.metabolite2 %}
Metabolite: {% reactionsmeta.metabolite2 %}
Stoichiometry: {% reactionsmeta.stoichiometry2 %}
{% endif %}
...
{% if reactionsmeta.metabolite60 %}
Metabolite: {% reactionsmeta.metabolite60 %}
Stoichiometry: {% reactionsmeta.stoichiometry60 %}
{% endif %}
Problems with the above:
It's terrably repetative
If the fields are in fact Foreign Keys their raw values wont't mean anything to the user.
EDIT: Response to comment that CharFields are in fact FKs.
So I think you need to query db for the information about the metabolites in the view and return that to the template. I think, by design, templates are not supposed to be able to access the db.
EDIT: I'm afraid you're going to have to learn how to write custom views. It's really not bad but it's hard to do some of the things you're attempting just using the generics.
https://docs.djangoproject.com/en/2.0/topics/http/views/

Categories

Resources