Django Fetching Data From DataBase Based on join Using ORM - django

I want to join two models as shown below and the join should be Harsha to Bank only(not Bank to Harsha)
model.py
class Harsha(models.Model):
name = models.CharField(max_length=255)
email = models.CharField(max_length=255)
class Bank(models.Model):
user = models.ForeignKey(Harsha, on_delete=models.CASCADE)
accountnumber = models.BigIntegerField()
ifsc = models.CharField(max_length=255)
branch = models.CharField(max_length=255)
bank = models.CharField(max_length=255)
views.py
test = Harsha.objects.all()
test1 = Bank.objects.all() # its working for me but i want join from Harsha table
in templates
# I want this
{% for tes in test %}
{{ tes.name }}
{{ tes.email }}
{{ tes.bank.accountnumber }} # how can I get this field
{{ tes.bank.ifsc }} # how can I get this field
{% endfor %}
# its working
{% for tes in test1 %}
{{ tes.user.name }}
{{ tes.user.email }}
{{ tes.accountnumber }}
{{ tes.ifsc }}
{% endfor %}

You can get it like this(using reverse relationship):
{% for tes in test %}
{{ tes.name }}
{{ tes.email }}
{% for bank in tes.bank_set.all %}
{{ bank.accountnumber }}
{{ bank.ifsc }}
{% endfor %}
{% endfor %}

Related

Django - Problem with DB query using foreign key

I'm using Django for a Web app and I have the following data model:
class classi(models.Model):
nome = models.TextField(null=True)
class Meta:
db_table = 'classi'
class users(models.Model):
name = models.TextField(null=True)
email = models.TextField(null=True)
password = models.TextField(null=True)
classe = models.ForeignKey(classi, db_column='classe', on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'users'
class smartphone(models.Model):
marca = models.TextField(null=True)
modello = models.TextField(null=True)
possessore = models.ForeignKey(users, db_column='possessore', on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'smartphone'
My goal is to show, on an HTML page, all classi, and for each classi all users and for each user all smartphone.
How can I implement my view.py and my html file?
The only solution that I found is to scan all table with a for loop and, through a condition, select the row using foreign key:
{% for c in classi %}
<p>{{ c.nome }}</p>
{% for u in users %}
{% if u.classe == c %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in smartphone %}
{% if s.possessore == u %}<p>{{ s.marca }}, {{ s.modello }}</p> {% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
Is there a better solution?
You could use backwards relations, which will only have items that have a connection
The general format is obj.{model}_set but you can also set it to something different in the models.py with the related_name attr in the ForeignKey field
{% for c in classi %}
<p>{{ c.nome }}</p>
{% for u in c.users_set.all %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in u.smartphone_set.all %}
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
{% endfor %}
{% endfor %}
Or, and this is probably cleaner:
Go the reverse way by looping through the smartphones in the top and just order smartphones by nome in the view with smartphoneList = smartphone.objects.all().order_by('possessore__classe__nome') so they are grouped together
{% for s in smartphoneList %}
<p>{{ s.possessore.classe.nome }}</p>
<p>{{ s.possessore.name }}, {{ s.possessore.email }}, {{ s.possessore.password }}</p>
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
Note after writing this I noticed #Lucas Grugru as already posted the reverse relations way.. From my testing it doesn't require pre-fetching, but it's probably a good idea to do that (I also have no idea). I'm still posting this because I think looping through smartphones might be a cleaner way of doing it
You can use *prefetch_related for prefetching related object from foreign key. More information: https://docs.djangoproject.com/fr/4.1/ref/models/querysets/#prefetch-related
The view:
def view(request):
classe = Classi.objects.all().prefetch_related("users_set").prefetch_related("users_set__smartphone_set")
context = {}
context["classe"] =) classe
return render(request, 'template.html', context)
And the html:
{% for c in classe %}
<p>{{ c.nome }}</p>
{% for u in c.users_set.all %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in u.smartphone_set.all %}
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
{% endfor %}
{% endfor %}

Django Template _set.all

I have this model:
class CustomerAddresses(models.Model):
ID = models.AutoField(primary_key=True)
...
CustomerID = models.ForeignKey('Customers', on_delete=models.CASCADE)
I render the Address Data in my Template:
% for address in customer_default_shipping_address %}
{% if address.Address_Company %}
<h5>{{ address.Address_Company }}<br/>
{{ address.Address_Firstname }} {{ address.Address_Lastname }}</h5>
{% else %}
<h5>{{ address.Address_Firstname }} {{ address.Address_Lastname }}</h5>
{% endif %}
<address class="mb-0 font-14 address-lg">
{{ address.Street}}<br>
{{ address.Zip}} {{ address.City}}<br>
{% for customer in address.customers_set.all %}
<abbr title="Telefon">P:</abbr> {{ customer.PhoneNumber }} <br/>
<abbr title="E-Mail">M:</abbr> {{ customer.Email }}
{% endfor %}
</address>
{% endfor %}
but the E-Mail and Phone Field will not be rendered, are I'm doing something wrong?
It looks like your relational model is wrong. A CustomerAddress only has one CustomerID linked to it because of the ForeignKey usage, thus you cannot look through address.customes_set.all.
Give it a go without the second nested loop and have just: address.customerID.PhoneNumber for example.

combining two or more querysets from different models in django

Main model:
class MainCategory(models.Model):
title = models.CharField(max_length=120, unique=True)
App#1:
class Category(models.Model):
title = models.CharField(max_length=120, unique=True)
main_category = models.ForeignKey(MainCategory, default=1, related_name='car_category')
App#2:
class Category(models.Model):
title = models.CharField(max_length=120, unique=True)
main_category = models.ForeignKey(MainCategory, default=1, related_name='classifieds_category')
on home page I want a combined list of both category list items as follows.
{% for object in main_cat_list %}
{{ object.title }}
{% for item in object.car_category %}
{{ item.title }}
{% endfor %}
{% endfor %}
How I can insert classifieds category also inside this list?
If you merely want to also display the classified_category as you have the car_category.
{% for object in main_cat_list %}
{{ object.title }}
{% for item in object.car_category %}
{{ item.title }}
{% endfor %}
{% for item in object.classified_category %}
{{ item.title }}
{% endfor %}
{% endfor %}

How to display in template value of foreign key?

models:
class ProductOpinion(models.Model):
user = models.ForeignKey(User)
product = models.ForeignKey(Product)
point = models.IntegerField()
class Product(models.Model):
name = models.CharField(max_length=255)
How to display in my template point of my ProductOpinion?
def index(request):
products = Product.objects.all()
return render_to_response('index.html',{'products':products}, context_instance=RequestContext(request))
template:
{% for p in products %}
{{ p.point }}
{% endfor %}
If yout want to acces the point field you have to do something like this:
{% for p in products %}
{% for productoption in p.productoptions_set.all %}
{{ productoption.point }}
{% endfor %}
{% endfor %}
You need to use:
{{ p.productopinion_set.all }}

ForeignKey. How to get data?

class Property(models.Model):
title = models.CharField(max_length=255)
class CurrentPrice(models.Model):
current = models.ForeignKey(Current)
prop = models.ForeignKey(Property)
price = models.DecimalField(max_digits=5, decimal_places=2)
class Current(models.Model):
name = models.CharField(max_length=20)
views.py:
...
p = Property.objects.all()
return render_to_response('index.html',{'p':p},context_instance=RequestContext(request))
How to get price of Property and display it in my template?
template:
{% for item in p %}
{{ item.title }}
{{ item.price }} # ???
{% endfor %}
I'm not sure what is your purpose/design of models, which doesn't look appropriate from what you have shown.
You will have many CurrentPrice per Property object, so in template you can do is
{% for item in p %}
{{ item.title }}
{% for cp in item.currentprice_set.all %}
{{ cp.price }}
{% endfor %}
{% endfor %}
If Property can have multiple CurrentPrice objects (what is by default):
{% for item in p %}
{{ item.title }}
{% for current_price in item.currentprice_set.all %}
{{ current_price.price }}
{% endofor %}
{% endfor %}
If only one (but in that case it is better to use o2o field instead of the FK fiel else it is up on you to prevent multiple CurrentPrice records pointing to the same Property):
{% for item in p %}
{{ item.title }}
{{ item.currentprice_set.get.price }}
{% endfor %}
I think what you're trying to do is something like that below.
class Property(models.Model):
title = models.CharField(max_length=255)
#property
def current_price(self):
# The current price is the last price that was given.
if self.pricing_history.count() > 0:
return self.pricing_history.order_by('-when')[0].amount
return None
class Price(models.Model):
prop = models.ForeignKey(Property, related_name='pricing_history')
amount = models.DecimalField(max_digits=5, decimal_places=2)
when = models.DateTimeField(auto_now_add=True)
example in template:
{% for item in p %}
{{ item.title }}
{{ item.current_price }}
{% endfor %}