Two models with one-to-many into single JSON dict - json

I have two models for 'PO Header' and 'PO Item' data like this:
class po(models.Model):
po_number = models.CharField(max_length=16, null=True)
buy_org = models.CharField(max_length=20, null=True)
supplier = models.CharField(max_length=16, null=True)
class poitm(models.Model):
po = models.ForeignKey(po, on_delete=models.CASCADE, related_name='poitm')
po_li = models.CharField(max_length=6, null=True)
matnr = models.CharField(max_length=16, null=True)
quantity = models.DecimalField(decimal_places=6, max_digits=16, null=True)
I try to create a view that returns a json object like this:
[{'po_number':'45000123','buy_org':'Org1','supplier':'Org2','itemlist':[{'po_li':'010','matnr':'123456','quantity':'12'},{'po_li':'020','matnr':'123457','quantity':'8'}]},{'po_number':'45000124','buy_org':'Org1','supplier':'Org2','itemlist':[{'po_li':'010','matnr':'123235','quantity':'15'},{'po_li':'020','matnr':'123499','quantity':'24'}]}
]
In principle a list of purchase orders with each purchase order containing a list of purchase order items.
I managed to create queryset containing the data like I need it but for performance reasons when using datatables.net with dom data I need to return the data in json format instead of looping through the queryset in the html template.
def purchaseorders(request):
polist=purchaseOrder.objects.all()
itemlist=poItem.objects.all()
for poentry in polist:
poentry.itemlist=itemlist.filter(po_id=poentry.id)
return render(request, 'purchaseorders.html', {"poitems":polist})
This seems to create a queryset with each object of a queryset. This then gives me a problem when I try to serialize it to json. Only the fields from the outer queryset are in the json result.
In the end the purpose is to generate an html page with a datatables.net table. Currently I am achieving this by looping through the inner and the outer queryset in the html page using django tags:
var data =[ {% for po in poitems %}
{ "ponumber": '{{ po.po_number}}', "buy_org": "{{ po.buy_org }}", "supplier": "{{ po.supplier }}","itemlist": [
{% for itemlist in po.itemlist %}
{ "poli": '{{ itemlist.po_li }}', "matnr": '{{ itemlist.matnr}}', "quantity": '{{itemlist.quantity}}'},
{% endfor %}
]},
{% endfor %} ]
This is a serious performance issue when I deal with a few thousand purchase orders. According to Datatables.net the correct way is to go with ajax and providing the data in json format.
I looked and tried for two solid days, turning in circles now, please help.

Related

Rendering data from a dictionary inside json after saving data into JSONField in Django

I am working on a django project whereby I am using JSONField to save data into the database of the model. Everything works fine but I am having issues when trying to render the data into the html template. The data saved into the database is as shown below.
{'degree': ['BSc','MSc'],
'designition': [
'content writer',
'data scientist',
'systems administrator',
],
'email': 'maunarokguy#gmail.com',
'name': 'Brian Njoroge',
'phone': '+918511593595',
'skills': [
'Python',
' C++',
'Power BI',
'Tensorflow',
'Keras',
'Pytorch',
'Scikit-Learn',
'Pandas',
'NLTK',
'OpenCv',
'Numpy',
'Matplotlib',
'Seaborn',
'Django',
'Linux',
'Docker'],
'total_exp': 3,
'university': ['gujarat university', 'wuhan university', 'egerton university']}
I am looking for a way to render them such that in the html, I will have something that displays the dictionary data inside skills and university as a list.
Here is the template for loop
{% for skill in user.profile.json_data %}
{{skill}}
{% endfor %}
And here is the models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(default='default.jpg', upload_to='profile_images')
bio = models.TextField()
resume = models.FileField('Upload Resumes', upload_to='resumes/', null=True, blank=True,default='resume.docx')
json_data = models.JSONField(null=True, blank=True)
Here is the views
#login_required
def myprofile(request, user_id):
profile = Profile.objects.get(id=user_id)
context = {'profile':profile}
return render(request, 'user/profile.html', context)

Django: Read image path field from MySQL

im curently making a mini product eshop for my studies. So I have the image path of products in MySQL database like LOAD_FILE(C:\\product.jpg) and I want to access the image from my Django project.
I have 2 questions. 1st, what Model Field should I use to read the image from the database's image path. And 2nd one how to read this image?
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.DecimalField(max_digits=7,decimal_places=2)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
The Models.ImageField is perfect for this. You don't need to it like this. Simply get your image in the template using {{ Product.image.url }} inside an img tag. Use If condition in templates such as {% if Product.image.url is not null %} <Show the picture> {% else %}<show some default image or show some text> {% endif %}

How to get the sum of a model field value from all the posts a user created in django base template?

I have a auth_user model, and a posts model. the posts model has fields like: id, author_id and likes. All I need print likes values related to each user in the base template. like:
{{ user.posts.likes }}
or
{{ user.user_id.posts.likes }}
This is my posts model:
class Post(models.Model):
title = models.CharField(max_length=150)
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.PositiveIntegerField(default=0, blank=True)
class Meta:
db_table = "posts"
def total_likes(self):
return self.likes
however it does not work, while {{ user.profile.image.url }} (profile is another model which has user_id) works perfectly.
I am importing base templates to other templates like {% extends "app/base.html" %} so I don't see any place in backend to pass the likes values
I believe the problem is that you're confusing a single Post for multiple posts and as a result there isn't an object to access. A user only has one profile, but as your code indicates they can have multiple posts as the author ForeignKey would indicate.
{{ user.post_set }} <- is a manager
{{ user.post_set.all }} <- is a queryset
{{ user.post_set.all.0 }} <- is the first item of the queryset
{{ user.post_set.all.0.likes }} <- should be the # of likes of the user's first post
Edit 1
The updated question could be restated as "how can I get the total number of likes a user has received via their posts"
There might be a way to accomplish that in the templates, but I think it's going to be difficult. I would put that number together in the view code. The key word that you're looking for is "aggregation"
https://docs.djangoproject.com/en/3.1/topics/db/aggregation/
from django.db.models import Sum
...
# inside your view
total_likes = user.post_set.all().aggregate(Sum('likes'))
Edit 2
Absolutely right #melvyn
Edit 3
In order to apply this to all pages without modifying the views you're going to have to write a context processor.
https://docs.djangoproject.com/en/3.1/ref/templates/api/#writing-your-own-context-processors
file: likes_context.py
from django.db.models import Sum
def likes_context_processor(request):
if request.user.is_authenticated:
posts = request.user.post_set.all()
total_likes = posts.aggregate(Sum('likes'))
else:
total_likes = 0
return {"total_likes": total_likes }
You'll need to locate that file appropriately and then add it to your context processors config in your settings.py
This might be helpful as well: creating my own context processor in django

How can i pass my data in sqlite database to templates? ( to make line chart using highcharts)

i'm developing web application using dJango.
My current situation is as below
When users do something, the data is saved into sqlite database
I want to pass my data to templates and draw line chart
I want X-axle : YYYY-MM-DD / Y-axle : the count of request
But, i have no idea how to make it.
{{ addRequestCnt }} is presented like as below.
"QuerySet [{'doDate':datetime.datetime(2019,4,15,0,0),'requestType__count':11}, {'doDate':datetime.datetime(2019,4,16,0,0),'requestType__Count':7}]>"
......
Thank you for helpful answer in advance.
My models.py
class ActivityLog(models.Model):
doDate = models.DateTimeField()
requestType = models.CharField(max_length=200)
My views.py
def dashboard(request):
addRequestCnt = ActivityLog.objects.filter(requestType='add').values('doDate').annotate(Count('requesetType'))
context = {
'addRequestCnt':json.dumps(addRequest, default=str),
}
return render(request,'dashboard.html',context)
Here is an example of a blog post model, our database schema
Here is how to return the data to the template a list view
And here is how to return data to the detail view
What you want on your template based on your model is something like this:
{% block content %}
<div class='col-sm-6 col-sm-offset-3'>
<h1>{{ doDate }}</h1>
<h2><small>{{ requestType }}</small></h2>
{% endblock content %}
Here is the official documentation for Django templates

Retrieve all related objects (reverse foreign keys) efficiently with django

I have the following models:
Car:
name = models.CharField(max_length=50)
model = models.CharField(max_length=80)
Driver:
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='drivers')
Now I want to retrieve all of cars including related model driver data
cars = Car.objects.prefetch_related('drivers').all()
Now in my template I just want to print each car and the first driver information
{% for car in cars %}
<tr>
<td>car.name</td>
<td>car.model</td>
<td>car.drivers.first.name</td>
<td>car.drivers.first.address</td>
</tr>
{% endfor %}
However, this results in 2k+ queries for around 500 cards in my db and it takes a while to load. Am I doing something wrong, is there anyway to make this more efficient?