Prusa
Prusa

Reputation: 179

Get Data Problem with Foreignkey Models QuerySet (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 %}

enter image description here

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 %}

Upvotes: 0

Views: 24

Answers (1)

Shmack
Shmack

Reputation: 2341

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.

Upvotes: 1

Related Questions