Get Data Problem with Foreignkey Models QuerySet (Django) - django

I am making django practising. I found a repo and edited to myself. When i came to the get data from models with foreignkey, i get query instead of data. I think my function is a little bit spagetti or my template file.
Full repo is here https://github.com/eseymenler/demo2
Here is the output of my codes. First red square is query, but i want second red square datas.
Hasta Adı: {{ patient.name }}
Hastanın Sağlık Problemi: {{ prob }}
Hastanın Boyu: {{ vital }}
Hastanın Sigara Kullanım Durumu: {{ social }}
First data {{ patient.name }} is very good for me. Thats what i want.
But when i get write {{ prob.problem }} it gives me nothing. So where is my fault.
But also when i make for loop like this, i get data which i want. So how can i fix this.
{% for y in prob %}
{{ y.problem }}
{% endfor %}
And my views.py
#login_required()
def patienttumbilgiListView(request, id):
patient = Patient.objects.get(aadhaarId = id)
prob = ProblemList.objects.filter(patient = patient)
vital = VitalSign.objects.filter(patient = patient)
social = SocialHistory.objects.filter(patient = patient)
return render(
request, 'patient_records/patient-problem-tum.html',
context={'prob': prob, 'vital': vital, 'social': social, 'patient': patient })
and my template file
{% extends 'base.html' %}
{% load static %}
{% load bootstrap4 %}
{% load i18n %}
{% block title %}problem-list-view{% endblock title %}
{% block content %}
<div class="container">
Hasta Adı: {{ patient.name }}</br>
Hastanın Sağlık Problemi: {{ prob }}<br>
Hastanın Boyu: {{ vital }}<br>
Hastanın Sigara Kullanım Durumu: {{ social }} <br></div>
<br>
<br>
<div class="container">
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-0lax{text-align:left;vertical-align:top}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-0lax">Hasta Adı:</th>
<th class="tg-0lax">{{ patient.name }}</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0lax">Hastanın Sağlık Problemi:</td>
<td class="tg-0lax">{% for y in prob %}<br> <br> {{ y.problem }}<br> <br> <br>{% endfor %}</td>
</tr>
<tr>
<td class="tg-0lax">Hastanın Boyu:</td>
<td class="tg-0lax">{% for x in vital %}<br> <br> {{ x.height }}<br> <br> <br>{% endfor %}</td>
</tr>
<tr>
<td class="tg-0lax">Sigara Kullanımı:</td>
<td class="tg-0lax">{% for item in social %}<br> <br><br> {{ item.tobacco_smoking_status }}<br> <br> <br>{% endfor %}</td>
</tr>
</tbody>
</table>
</div>
<br>
<br>
{% endblock %}

Roughly What You Had
So your code is:
#login_required()
def patienttumbilgiListView(request, id):
patient = Patient.objects.get(aadhaarId = id)
prob = ProblemList.objects.filter(patient = patient)
vital = VitalSign.objects.filter(patient = patient)
social = SocialHistory.objects.filter(patient = patient)
return render(
request, 'patient_records/patient-problem-tum.html',
context={'prob': prob, 'vital': vital, 'social': social, 'patient': patient })
{% for y in prob %}
{{y.problem}}
{% endfor %}
{% for x in vital %}
{{x.height}}
{% endfor %}
{% for item in social %}
{{item.tobacco_smoking_status}}
{% endfor %}
Some Friendly Suggestions
"id" is a reserved word / function - I suggest changing id to maybe pid in your code.
Return an error to your view - You don't necessarily have to make this change, but I think its a good idea, and can even help with troubleshooting. I mean you should probably be returning an error or something to this chart if you can't find these objects with those ids in your database.
"get()" throws a DoesNotExist error if the id isn't found - You should catch the error and return it to the console you are making or do something like that.
views.py
#login_required()
def patienttumbilgiListView(request, pid):
context = {}
try:
patient = Patient.objects.get(aadhaarId = pid)
except DoesNotExist:
context['error'] = f"Could not find patient with id '{pid}'."
else:
context['prob'] = ProblemList.objects.filter(patient=patient)
context['vital'] = VitalSign.objects.filter(patient=patient)
context['social'] = SocialHistory.objects.filter(patient=patient)
context['patient'] = patient
return render(request, 'patient_records/patient-problem-tum.html', context=context)
template.html
{% if error %}
{{error}}
{% endif %}
{% for y in prob %}
{{y.problem}}
{% empty %}
Could not find problems.
{% endfor %}
{% for x in vital %}
{{x.height}}
{% empty %}
Could not find vitals.
{% endfor %}
{% for item in social %}
{{item.tobacco_smoking_status}}
{% empty %}
Could not find socials.
{% endfor %}
What Your Problem Is And How To Solve It
I am making django practising. I found a repo and edited to myself. When i came to the get data from models with foreignkey, i get query instead of data.
Based on this quote, I am assuming you want to know why the data is being returned as a queryset instead of as a singular result. From the docs:
filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element. If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly: one_entry = Entry.objects.get(pk=1).
Which is why you should use the for loop in your template.html. If you don't want to use that, then you should preprocess this data either by using get() instead of filter() or simply, in the context, send the [0] element to the template from your view.
So, to clarify, if you want to use {{prob.problem}} in your template, you need to change your view to either do prob = ProblemList.objects.filter(patient = patient)[0] or prob = ProblemList.objects.get(patient = patient). If you choose the first, you should check the length (prob = prob[0] if len(prob) == 1 else None), otherwise, if you choose the latter, you should wrap it with a try, except, else clause like this:
try:
prob = ProblemList.objects.get(patient=patient)
except DoesNotExist:
context['error'] = "Could not find ProblemList."
print("Does Not Exist")
else:
context['prob'] = prob
or you could just use the for loop that you have in place, I don't know how many entries you are expecting the query set to have per patient.
If I need to further clarify anything, please let me know.

Related

How to paginate multiple queries in a single function-based-view or class-based-view in django?

I have a search function that queries multiple models. I have the expected results displayed in a html template and so far all is fine. The problem is that I want to paginate the results using django's built in Pagination class. Pagination with multiple models is where I'm now stuck. I have other class based views working well paginating single models.
def search_results(request):
if request.method == 'POST':
searched = request.POST['searched']
books = Book.objects.filter(description__icontains=searched,
title__icontains=searched).order_by('-id')
sermons = Sermon.objects.filter(description__icontains=searched,
title__icontains=searched).order_by('-id')
other_sermons = SermonsByOtherFathers.objects.filter(description__icontains=searched,
title__icontains=searched).order_by('id')
other_books = BooksByOtherFathers.objects.filter(description__icontains=searched,
title__icontains=searched).order_by('-id')
context = {
'searched': searched,
'sermons': sermons,
'other_sermons': other_sermons,
'books': books,
'other_books': other_books,
}
if searched == "":
return HttpResponse('Please type something in the search input.')
return render(request, "search_results.html", context)
This is a simplified version of my html template.
{% for book in books %}
<tr>
<td>
{{ book.title }}
<p> {{book.author}} </p>
<p> {{ book.category }} </p>
<p> {{ book.description }} </p>
</td>
</tr>
{% endfor %}
<-- ...and the same loops goes for the rest of the other querysets. -->
{% for book in other_books %}
<-- code here -->
{% endfor %}
{% for sermon in sermons %}
<-- code here -->
{% endfor %}
{% for sermon in other_sermons %}
<-- code here -->
{% endfor %}
Any help with the django multiple-model pagination part will be appreciated.

Check whether value in dict with for loop in Django's template

I have the following data in my views.
months = [1,2,3,4,5,6,7,8,9,10,11,12]
mydict = {3:'a',4:'b'}
The key means month,if this month exists value,then render the value,else leave blank.
Here's my template.
{% for j in months %}
{% if mydict.j %}
<th class="align-middle">{{ mydict.j }}</th>
{% else %}
<th class="align-middle"></th>
{% endif %}
{% endfor %}
But the result always is blank.
I can access the value by mydict.3,but i can't get the value by mydict.j with a forloop.
If you write {{ mydict.j }}, then Django aims to lookup the value mydict['j'], not mydict[j].
Dictionary lookups and function calls (with arguments) are deliberately not allowed in a template, such that developers are encouraged to write business logic in the view not in the template. You can write a custom template filter, or make use of the jinja template renderer to allow this.
But it might be more sensical to do the mapping in the view:
def some_view(request):
mydict = {3:'a',4:'b'}
monthsanddict = [(x, mydict.get(x)) for x in range(1, 13)]
return render(request, 'some_template.html', {'monthsanddict': monthsanddict})
and in the template, you can then render this with:
{% for j, mydictj in monthsanddict %}
{% if mydictj %}
<th class="align-middle">{{ mydictj }}</th>
{% else %}
<th class="align-middle"></th>
{% endif %}
{% endfor %}

Display Django model data to table in HTML

I have two Django models that record time. Model one records time during the morning and Model two records time during the evening. I want to present both of these times along with the difference between the times within an HTML table but am confused about how to do it. I am new to Django and would really appreciate some advice.
This is what I have so far:
models.py:
class Alltime(models.Model):
id= models.ForeignKey(User, on_delete = models.CASCADE)
mtime = models.DateTimeField()
etime = models.DateTimeField()
views.py:
def panel(request):
time_data = User.objects.filter(pk__gt=1) #I need all data except for the default Super User account
get_time = Alltime.objects.all()
return render(request, 'users/interface.html', {'data': time_data, "get_time": get_time})
panel.html:
<form>
{% csrf_token %}
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for data in data %}
<tr>
<td>{{data.username}}</td>
{% endfor %}
{% if get_time %}
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
{% endfor %}
{% else %}
<td> Not available </td>
{% endif %}
</tr>
</table>
</form>
How can I get the difference between the times and place them within the HTML table?
If I understand correctly what you want to do, then you can/need to structure your data differently. An easy way is to prepare the data in your view:
def panel(request):
time_data = User.objects.filter(pk__gt=1)
time_table=[]
for user in time_data:
morning_time = Morning.objects.filter(user=user)
evening_time = Evening.objects.filter(user=user)
diff = morning_time - evening_time
time_table.append((user.name, morning_time, evening_time, diff))
return render(request, 'users/interface.html', {'data': time_table})
And in the template:
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for line in data %}
<tr>
<td>{{line.0}}</td>
<td>{{line.1}}</td>
<td>{{line.2}}</td>
<td>{{line.3}}</td>
</tr>
{% endfor %}
</table>
You need to add the handling of not existing data in the view code.
Some remarks:
The whole thing does not really make sense to me. I guess you will need to filter for dates too. But you should get the idea from this. And why is it in a form?
You can add a property to the Alltime model that returns the difference between the morning and evening time
#property
def diff(self):
return self.etime - self.mtime
Then in your template you can use this property
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
<td>{{m.diff}}</td>
{% endfor %}

Performance problems while creating multiple objects

My aim is to create a matrix with individual editable fields. Since different people should only be allowed to edit certain fields I thought about creating an object called CellCE and an object level permission.
my models.py
class CellCE(models.Model):
row = models.ForeignKey('Descriptor',related_name='activecell', on_delete=models.CASCADE)
col = models.ForeignKey('Descriptor',related_name='passivecell', on_delete=models.CASCADE)
val = models.IntegerField(default=0)
project = models.ForeignKey('Project', on_delete=models.CASCADE, default='1')
#permission for Cells
class Meta:
permissions = (
("edit_cellCE", "Has permission to edit value of Cause and Effect cell"),
)
#classmethod
def create(cls, row, col, project):
CellCE = cls(row=row, col=col, project=project)
CellCE.save()
return CellCE
my views.py
def phase2(request, id):
projectname = get_object_or_404(Project, pk=id)
projectid = id
project = Project.objects.get (id=projectid)
projectdescriptors = Descriptor.objects.filter( project=projectid)
for Descriptor.id in projectdescriptors:
row = Descriptor.id
for Descriptor.id in projectdescriptors:
col = Descriptor.id
if CellCE.objects.filter(row=row, col=col, project=project).exists():
pass
else:
obj = CellCE.create(row, col, project)
CellCElist = CellCE.objects.filter(project= project)
context = {'CellCElist': CellCElist, 'projectname': projectname, 'projectid': projectid, 'projectdescriptors': projectdescriptors}
return render(request, 'szenario/phase2.html', context)
my template
<table>
{% for drow in projectdescriptors %}
{% if forloop.first %}
<tr>
<th align="left">Descriptors</th>
{% for value in projectdescriptors %}
<th>{{value}}</th>
{% endfor %}
</tr>
{% endif %}
<tr>
<th align="left">{{drow}}</th>
{% for dcol in projectdescriptors %}
<td align="center">
{% if forloop.parentloop.counter == forloop.counter %}
-
{% else %}
{% for CellCE in CellCElist %}
{% if CellCE.col == dcol %}
{% if CellCE.row == drow %}
Value =
{{CellCE.val}}
{% endif %}
{% endif %}
{% endfor %}
<form method="post">
{% csrf_token %}
<input type="submit" value="+1">
<input type="submit" value="-1">
</form>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
The number of descriptors determins the size of the matrix. With every Descriptor over 15> loading the page takes longer or doesnt work at all. I am using SQLLite.
Question: How can I increase the loadingspeed and make this work at all? Does a change of DB solve the Problem or should i overthink my concept.
Any Help is appreciated.

Django nested QuerySet yielding nothing

I am using Django 1.8 with Postgres 9.2 on a Windows 8 machine.
I have two pieces of nearly identical code from two of my projects. One works and the other doesn't.
Here's the code that works:
# views.py
from django.shortcuts import render
from models import Artist, Track
def music(request):
artists = Artist.objects.all().order_by('orderName')
artistTrackCollections = []
for artist in artists:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
artistTrackCollections.append(artist)
return render(request, 'music.html', {'artistTrackCollections': artistTrackCollections,})
And the relevant template code:
{% for artist in artistTrackCollections %}
<dl>
<dt>
{% if artist.website %}
<h2>{{ artist.name }}</h2>
{% else %}
<h2>{{ artist.name }}</h2>
{% endif %}
</dt>
<dd>
<ul>
{% for track in artist.tracks %}
<li>“{{ track.title }}”
<i>({{ track.album.title }})</i>
{% endfor %}
</ul>
</dd>
</dl>
{% endfor %}
Now here's pretty much the exact same code from a different project of mine that doesn't work anymore:
def index(request):
productList = PartModel.objects.filter(isBuild=True, isActive=True).order_by('name')
productCollection = []
for product in productList:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
productCollection.append(product)
return render(request, 'index.html', { 'productCollection': productCollection, })
and its corresponding template:
{% for product in productCollection %}
<p>{{ product.name }}
<p>${{ product.price }}
<ul>
{% for part in product.part_list %}
<li>{{ part.family.type.name }} | {{ part.name }}
{% endfor %}
</ul>
{% endfor %}
This code used to work but now it doesn't. In the code that works I succeed in going through each artist and attaching that artist's tracks. In the code that fails I try to go through each PartModel instance that is a build and get that PartModel instance's corresponding parts. They are identical as far as I can tell. productCollection gets populated but the part_list data for some reason is blank. This leads me to believe the problem is with this line:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
But I cannot discern the difference from this line:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
Thanks in advance for any help!