how to write 3 dependant table join query in Django - django

I am new in django , I want to create join query in django, my model is as follow
Model.py
Class area_country(models.Model):
country_id = models.AutoField(primary_key=True)
country_name = models.CharField(max_length=100, null=True)
short_name= models.CharField(max_length=20, null=True)
flag_enable = models.SmallIntegerField()
class Meta:
db_table = "area_country"
class area_state(models.Model):
state_id = models.AutoField(primary_key=True)
state_name = models.CharField(max_length=100, null=True)
short_name = models.CharField(max_length=20, null=True)
country_id = models.ForeignKey(area_country, on_delete=models.CASCADE)
flag_enable = models.SmallIntegerField()
class Meta:
db_table = "area_state"
class area_city(models.Model):
city_id = models.AutoField(primary_key=True)
city_name = models.CharField(max_length=100, null=True)
short_name = models.CharField(max_length=20, null=True)
state_id = models.ForeignKey(area_state, on_delete=models.CASCADE)
flag_enable = models.SmallIntegerField()
class Meta:
db_table = "area_city"
i need query like
SELECT "area_country"."country_id",
"area_country"."country_name",
"area_state"."state_id",
"area_state"."state_name",
"area_city"."city_id",
"area_city"."city_name"
FROM "area_country"
LEFT OUTER JOIN "area_state" ON ("area_country"."country_id" = "area_state"."country_id_id")
LEFT OUTER JOIN "area_city" ON ("area_state"."state_id" = "area_city"."state_id_id")
** Try by me **
view.py
result = area_country.objects.all().select_related('area_state').values('country_id', 'country_name', 'area_state__state_id', 'area_state__state_name')
when i print it by using query = result.query
SELECT "area_country"."country_id", "area_country"."country_name", "area_state"."state_id", "area_state"."state_name"
FROM "area_country"
LEFT OUTER JOIN "area_state" ON ("area_country"."country_id" = "area_state"."country_id_id")
this is ok now i try
result = area_country.objects.all().select_related('area_state').select_related('area_city').values('country_id', 'country_name', 'area_state__state_id', 'area_state__state_name','area_city__city_id','area_city__city_name')
it show me error
Cannot resolve keyword 'area_city' into field. Choices are: area_state, country_id, country_name, flag_enable, short_name
please help me for django query.
for information friends, i know how to write raw query in django with cursor = connection.cursor()

finally solution is,
let me clear . i want array for js datatable thats why temp = [] and also i want json response so JsonResponse,
view.py
class get_all_country_state_city(View):
def get(self, request):
citys = area_city.objects.all()
response = []
if citys:
response = []
for value in citys:
temp = []
temp.append(value.city_name)
temp.append(value.state_id.state_name)
temp.append(value.state_id.country_id.country_name)
response.append(temp)
return JsonResponse({'data': response})
if you want to show directly in template then
view.py
citys = area_city.objects.all()
context = {
'citys':citys
}
return render(request, "area.html", context)
template.html
<table >
<tbody>
{% for value in citys %}
<tr><td>{{value.state_id.country_id.country_name}}</td>
<td>{{value.state_id.state_name}}</td>
<td>{{value.city_name}}</td></tr>
{% endfor %}
</tbody>
</table>

Related

Django query is not returning all the records

I am trying to do a simple query but I just don’t understand why I am only getting 1 row when it should be in this example 2:
And I am trying to get all the rows where the externalID = 45454
By doing:
context['report'] = Report.objects.filter(externalID = self.kwargs.get('reportID'))
I can see on the debug I get
SELECT "data_app_report"."id", "data_app_report"."main_contact_id", "data_app_report"."company_id", "data_app_report"."created", "data_app_report"."externalID", "data_app_report"."success", "data_app_report"."amountrequested" FROM "data_app_report" WHERE "data_app_report"."externalID" = '''45454'''
And my table looks like
I guess I am doing something wrong in the query but I just don’t know what, I thought having filter will allow me to get all of the records
This are the 2 models:
class Report(models.Model):
main_contact = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
company = models.ForeignKey(CompanyDetail, on_delete=models.CASCADE, related_name='companyreport', default=1)
created = models.DateTimeField(auto_now_add=True)
externalID = models.CharField(default='0000000', max_length=35, unique = False, editable=False) #ONE PERSON CAN HAVE MULTIPLE BANKING IN THE SAME OPP, THEN THE REF IS THE SAME
success = models.BooleanField(default = True)
amountrequested = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
class ReportURL(models.Model):
report = models.ForeignKey(Report, on_delete=models.CASCADE, related_name='reporturls')
file_type = models.CharField(max_length=5, unique = False, default='html')
report_url = models.URLField(unique=True)
This is my view
class ExtAccView(TemplateView):
template_name = 'data_app/ext_access.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['reportID'] = self.kwargs.get('reportID')
context['access'] = self.kwargs.get('access')
#GET THE COMPANY INFORMATION
try:
context['company'] = CompanyDetail.objects.get(companyExternalKey = self.kwargs.get('access'))
except Exception as e:
context['message'] = 'The company doesnt match the values you submitted ' + self.kwargs.get('access')
return context
#GET THE REPORT AND WE NEED TO DOUBLE CHECK IF THE REPORT COMPANY IS THE SAME AS ABOVE
try:
# context['report'] = Report.objects.get(externalID = self.kwargs.get('reportID'))
context['report'] = Report.objects.filter(externalID = self.kwargs.get('reportID'))
except Exception as e:
context['message'] = 'No reports found with that reference: ' + self.kwargs.get('reportID')
return context
return context
This is my template (ext_access.html)
{% for r in reportURL %}
{{ r.report_url }}
{% endfor %}

Get item from Django database model

I'm new to Django and I'm trying to get the item from the database.
The problem is the item is saved as a list in Django. And item[i] is not helping either. Please help me figure it out how to get the data
in the shell, I have tried
for x in NewsItem.objects.all():
print(x.tag)
this will print
['babi kutil', 'babi hutan', 'babi liar', 'hutan indonesia']
['ibu aniaya anak']
['pilkada serentak 2018', 'bandung', 'nurul arifin', 'pilwalkot bandung 2018']
['narkoba di surabaya', 'bnnp jatim']
['pilkada serentak 2018', 'banten']
But I want to get each item, not as a list.
The NewsItem Model.
class NewsItem(models.Model):
breadcrumbs = models.CharField(max_length=150, null=True)
penulis = models.CharField(max_length=100, null=True)
judul = models.CharField(max_length=200, null=True)
berita = models.TextField()
tag = models.TextField(null=True)
url = models.CharField(max_length=200, unique = True)
website = models.CharField(max_length=50, null=True)
date = models.DateTimeField()
#property
def to_dict(self):
data = {
'data': json.loads(self.url),
'tanggal': self.tanggal
}
return data
def __str__(self):
return self.url
You can use 2 for loops to achieve this and as you have mentioned tag as TextField, so you need to split it on comma.
for x in NewsItem.objects.all():
tag_text = x.tag[1:-1]
tag_list = tag_text.split(",")
for tag in tag_list:
print(tag)

django form not updating as expected

Here is my model:
class Browser(models.Model):
profile_name = models.CharField(max_length=400)
browser_type = (
('fr', 'Firefox'),
('ch', 'Chrome'),
('op', 'Opera'),
('ot', 'Other'),
)
browser_name = models.CharField(choices=browser_type, max_length=2)
device_name = models.CharField(max_length=400)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Bookmark(models.Model):
browser = models.ForeignKey(Browser, on_delete=models.CASCADE, null=True, blank=True)
title = models.TextField()
url = models.TextField()
iv = models.TextField()
salt = models.TextField()
iteration = models.IntegerField(default=1500)
tags = TaggableManager()
I only want to update certain fields, so here is the modelform
class BookmarkFormEdit(ModelForm):
class Meta:
model = Browser
exclude = ('tags', 'browser_name', 'device_name', 'profile_name')
but my problem is, values are not updating as expected . Here is the view:
def bookmark_edit(request, pk=None):
if request.method == 'POST':
bookmark = Bookmark.objects.get(pk=pk)
frm = BookmarkFormEdit(request.POST, instance=bookmark)
print(request.POST.get('iteration')) // printing correct value from front-end
if frm.is_valid():
x = frm.save()
print(x.iteration) // not saving the new value !
return JsonResponse({'status': 'created'})
else:
return JsonResponse({'error': frm.errors})
return render(request, 'bookmark_edit.html', {'pk': pk})
You are incorrectly defined model in the form. You should use Bookmark model instead of Browser.
class BookmarkFormEdit(ModelForm):
class Meta:
model = Bookmark
You may need to define fields to include/exclude as you want for this model.

Save a list of objects in model as a field

I'm trying to write internet-shop, and I have a model Order:
class Order(models.Model):
state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
order_date = models.DateTimeField(auto_now_add=True)
delivery_time = models.CharField(max_length=100)
address_city = models.CharField(max_length=40)
address_street = models.CharField(max_length=40)
address_building = models.CharField(max_length=40)
state = models.CharField(max_length=200, default='ACTIVE')
products = models.ForeignKey(OrderProduct)
client = models.ForeignKey(CustomUser)
And OrderProduct:
class OrderProduct(models.Model):
product = models.ForeignKey(Product)
product_ammount = models.IntegerField()
As you can see, user can add to order different products and different ammount of each product. So, with current models, I can add to order only one type of product. Then I rewrite it in the next way:
class Order(models.Model):
state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
order_date = models.DateTimeField(auto_now_add=True)
delivery_time = models.CharField(max_length=100)
address_city = models.CharField(max_length=40)
address_street = models.CharField(max_length=40)
address_building = models.CharField(max_length=40)
state = models.CharField(max_length=200, default='ACTIVE')
client = models.ForeignKey(CustomUser)
class OrderProduct(models.Model):
product = models.ForeignKey(Product)
order = models.ForeignKey(Order)
product_ammount = models.IntegerField()
And in a view, when I need to get a user's orders, I just do next: Order.objects.get(client=request.user).orderproduct_set
But I think that it's not correct. How to rebuild these models to gain the desired result?
In my opinion the second approach is perfectly fine.
One small error in the question is that the query uses get() instead of filter(). This will lead to an exception once one user has more than one order.
So, instead of the get() it would be:
orders = Order.objects.filter(client=request.user)
for order in orders:
print order.orderproduct_set.all()
To use this in a template (question from the comments) it is enough to pass the orders:
views.py
class MyView(View):
def get(self, request):
ctx = {
'orders': Order.objects.filter(client=request.user)
}
return render(request, 'my/template.html', ctx)
my/template.html
{% for order in orders %}
{% for item in order.orderproduct_set.all %}
{{ item.product_amount }}x {{ item.product }}<br/>
{% endfor %}
{% endfor %}

Queries over ManyToManyField with variable set in a sessions user

Here is my models:
class Clients(models.Model):
client_name = models.CharField(max_lenght=100)
commentaire_clients = models.TextField(blank=False)
date_demande = models.TimeField(auto_now_add=True)
choix = models.ManyToManyField('Agence', blank=True)
def __unicode__(self):
return unicode(self.date_demande)
class Market(models.Model):
nom_market = models.CharField(max_length=200)
code_postal_market = models.ManyToManyField('Lieux', blank=True)
statut_vip = models.BooleanField(default=False)
def __unicode__(self):
return self.nom_market
class Lieux(models.Model):
code_postal = models.CharField(max_length=200)
ville = models.CharField(max_length=200)
region = models.CharField(max_length=200)
departement = models.CharField(max_length=200)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
latitude = models.DecimalField(max_digits=9, decimal_places=6)
pays = models.CharField(max_length=100)
def __unicode__(self):
return unicode(self.code_postal)
Here is my view:
def comparelist(request):
if request.session.get('code_postal'):
poste = request.session.get('code_postal')
else:
poste = "RATE"
market_match = Market.objects.filter(statut_vip=False, code_postal_market = poste)
market_match_vip = Market.objects.filter(statut_vip=True)
#edit bis repetita Market replace Agence models
return render_to_response('compare.html', {
'code_postale': poste,
'bien_immobilier': bien,
'listing_agence' : market_match ,
'listing_vip' : market_match_vip ,
})
What I am trying to do is to make a query that will give me all the market that match:
- statut_vip = False
- code_postal_market = poste (that I obtain from user session from a form on the previous page
then I try to render it in my templates via:
{% for mes_market in listing_vip %}
<br>{{mes_market.nom_market}}
<br>{{mes_market.statut_vip}}
{% endfor %}
edit
here is my template for listing_agence (same as the previous one but with the right reference) sorry for the error.
{% for mes_agences in listing_agence %}
<br>{{mes_agences.nom_market}}
<br>{{mes_agences.statut_vip}}
{% endfor %}
My second queries to list all VIP clients do work but when I try to filter via the postal code given by the user via a form (and keeping the record via sessions)
nothing appears.
Thank you for your help!
I finally made it!
I replaced:
market_match = Market.objects.filter(statut_vip=False, code_postal_market = poste)
by
market_match = Market.objects.filter(statut_vip=False, code_postal_market__code_postal=poste)
code_postal is from the table Lieux