I want to learn django and I should categorize my sql inputs according to my models.
For example I have some models like this:
class Author(models.Model):
authorName = models.CharField(max_length=30)
def __str__(self):
return self.authorName
class Book(models.Model):
author = models.ForeignKey(Authors, on_delete=models.CASCADE)
bookName = models.CharField(max_length=60)
downloadLink = models.FileField()
downloadCount = models.IntegerField(default=0)
def __str__(self):
return self.bookName
and I want to an output in my .html file like this;
Sherlock Holmes
A Study in Scarlet
The Sign of the Four
The Hound of the Baskervilles
Suzanne Collins
The Hunger Games
Catching Fire
Mockingjay
I tried this code in my html file but it doesn't work
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in all_books %}
{% if book.author == author.authorName %}
<li>{{ book.bookName }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
My output is;
Sherlock Holmes
Suzanne Collins
Here is my view.py file;
def books(request):
return render(request,'../templates/library/library-template.html', {
'all_authors': Author.objects.all(),
'all_books': Book.objects.all(),
})
How can I fix it? Or are there any different solution for fix this?
Thank you.. :)
Your if statement will never be true, you are comparing an object and a string
{% if book.author == author.authorName %}
So you could change this to
{% if book.author == author %}
But this is still wasteful, you can just use the reverse lookup so you won't need the if statement at all
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in author.book_set.all %}
<li>{{ book.bookName }}</li>
{% endfor %}
{% endfor %}
</ul>
I want to define a queryset. In the shell it is all fine and I can filter the column I want with:
pat1 = Patient.objects.get(pk=1)
pat1.examinationgeometry_set.filter(examination='FIRST')
now I want to define a QuerySet out of it but I don't know where to define it and how. In the Views, Templates, Models? And how do I write it? I know that I have to define it with a function but is there any function from django for it?
Idea behind this queryset is to show all of the results in my database from the first examination. So in my template I have sth like this:
{% if Patient.examinationgeometry_set.filter(examination='FIRST') %}
{% for geo in patient.examinationgeometry_set.all %}
<li> x: {{ geo.x }}<br/>
c: {{ geo.c }} <br/>
b: {{ geo.b}}<br/>
n: {{ geo.n}}<br/>
</li>
{% endfor %}
{% endif %}
I am thankful for every hint!
Querysets should be made in the view, not in the template, given your code, it should be something like this:
view.py:
def my_view:
patients = Patient.objects.all()
context = {"patients": patients}
return render(request, "template_path", context)
template.html:
{% for patient in patients %}
{% for geo in patient.examinationgeometry_set.all %}
{% if geo.examination == 'FIRST' %}
<li>
x: {{ geo.x }}<br/>
c: {{ geo.c }}<br/>
b: {{ geo.b}}<br/>
n: {{ geo.n}}<br/>
</li>
{% endif %}
{% endfor %}
{% endfor %}
A better option is to make a python property for your patient model like this:
class Patient(stuff):
# your model stuff
#property
def first_examinationgeometry_set():
# maybe this should use .get() instead of filter?
return self.examinationgeometry_set.filter(examination="FIRST")
and now call this in the template(same view as first example):
{% for patient in patients %}
{% with geo=patient.first_examinationgeometry_set %}
<li>
x: {{ geo.x }}<br/>
c: {{ geo.c }}<br/>
b: {{ geo.b}}<br/>
n: {{ geo.n}}<br/>
</li>
{% endwith %}
{% endfor %}
I am trying to get a list of all manuscripts in my db, print out the shelfmarks for each of them and in case that they are linked to other manuscripts also print out the shelfmarks of those manuscripts.
Here is what my models look like:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
MSSLink = models.ManyToManyField('self',through='MSSLink',symmetrical=False)
[...]
class MSSLink(models.Model):
link1 = models.ForeignKey('MSS', related_name='First_MSS')
link2 = models.ForeignKey('MSS', related_name='Second_MSS')
[...]
Here is the code in views.py
def show_all_MSS(request):
all_MSS = MSS.objects.select_related().all() # get all MSS
t = loader.get_template('list.html')
c = Context({'all_MSS': all_MSS, })
return HttpResponse(t.render(c))
The question is then what to do in my template. I thought about doing something like this, but I don't know how I can test whether the current MS in the for-loop has been linked to another MS and if so how to display those shelfmarks:
{% if all_MSS %}
<ul>
{% for i in all_MSS %}
<li>{{ i.shelfmark }}</li>
{% if i.MSSLink %}
<p>This MS is linked to the following MSS: {{ i.MSSLink.link1 }}</p>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No MSS found</p>
{% endif %}
Your models are a bit complicated - you can probably get rid of MSSLink:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
links = models.ManyToManyField('self', symmetrical=False, blank=True)
def __unicode__(self):
return self.shelfmark
and add this to your template:
{% if i.links.all %}
<ul>
{% for l in i.links.all %}
<li>{{ l.shelfmark }}</li>
{% endfor %}
</ul>
{% endif %}
The problem I'm struggling with is as follows:
I have:
{% for field in form %}
{{ field }}
{% end for %}
What I want is to put an 'if' statement to exclude a field which .label or whatever is provided. Like:
{% for field in form%}
{% if field == title %}
{% else %}
{{ field }}
{% endif %}
{% endfor %}
Is it possible? I have to many fields to write them one by one and only one or two to exclude.
Thank you for any tips.
BR,
Czlowiekwidmo.
Yes, this should be possible:
{% for field in form %}
{% ifnotequal field.label title %}
{{ field }}
{% endifnotequal %}
{% endfor %}
Django's template tags offer ifequal and ifnotequal variants, and you can test the field.label against either a context variable, or a string.
You might be a lot happier creating a subclass of the form, excluding the offending field.
See http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance
class SmallerForm( MyForm ):
class Meta(MyForm.Meta):
exclude = [ title ]
{% for field in form %}
{% if field.name != 'field_name' %}
{{ field }}
{% endif %}
{% endfor %}
I am using Django, PyCharm 2018.3.7, Python 3.7, and Postgres.
Unfortunately, I do not understand how to display on one screenpage (Django form) the results for 2 separate querysets that need the same ID passed by a dynamic filter request (GET). There is a table/model (ASSIGNMENTS) with a One-To-Many relationship to another table/model (PRODUCTS). The ID being passed is the ASSIGNMENTS.ID, which is the PK of ASSIGNMENTS and the FK of PRODUCTS.
I am not trying to join these 2 querysets. I need the user to see the information for the ASSIGNMENT first and then below I want them to see all of the PRODUCTS that belong to that ASSIGNMENT.
I do not need to update/create data, so no POST is needed. Only want to retrieve, GET, data that exists.
Below are the code for models.py, views.py, and templates. It works perfect with just ASSIGNMENTS.
MODELS.PY
class Assignments(models.Model):
id = models.DecimalField(db_column='ID', primary_key=True, max_digits=9, decimal_places=0)
name = models.CharField(db_column='NAME', unique=True, max_length=40)
def __str__(self):
return self.name + ' ' + '(' + '#' + str(self.id) + ')'
class Meta:
ordering = 'name',
db_table = 'ASSIGNMENTS'
class Products(models.Model):
id = models.DecimalField(db_column='ID', primary_key=True, max_digits=11, decimal_places=0)
assignment = models.ForeignKey(Assignments, models.DO_NOTHING, related_name='productsfor_assignment', db_column='ASSIGNMENT_ID', blank=True, null=True)
name = models.CharField(db_column='NAME', max_length=80)
def __str__(self):
return self.name + ' ' + '(' + '#' + str(self.id) + ')'
class Meta:
ordering = 'name',
db_table = 'PRODUCTS'
VIEWS.PY
def search_form(request):
return render(request, 'assignments/search_form.html')
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assign = Assignments.objects.filter(id__icontains=q)
return render(request, 'assignments/search_results.html',
{'AssignmentsResults': assign, 'query': q})
else:
# if the query is empty, render the 'search_form html' template again.
# display an error message in that template. So, pass a template variable.
# 'search_form html' will check for the 'error' variable
return render(request, 'assignments/search_form.html', {'error': True})
TEMPLATE 'search_form.html'
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Form </h1>
<br><br>
{% if error %}
<p style="color: red;">Please submit a search term.</p>
{% endif %}
<form action="/search/" method="get">
<input type="text" name="q" placeholder="Enter ID here ...">
<input type="submit" value="Search">
</form>
<p>
Page last updated: {{ last_updated|date:'D d F Y' }}
</p>
{% endblock content %}
TEMPLATE 'search_results.html'
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Results</h1>
<p>You searched for: <strong>{{ query }}</strong></p>
{% if AssignmentsResults %}
<ul>
{% for assignments in AssignmentsResults %}
<li>
{{ assignments.id }}, {{ assignments.name }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
{% endblock content %}
This is what I finally put together to include Products (shown below in the failed views.py and template). But, it does not work.
This was the FAILED VIEWS.PY
def search_form(request):
return render(request, 'assignments/search_form.html')
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assign = Assignments.objects.filter(id__icontains=q)
prod = Products.objects.filter(assignment__icontains=q)
return render(request, 'assignments/search_results.html',
{'AssignmentsResults': assign, 'query': q})
return render(request, 'assignments/search_results.html',
'ProductsResults': prod, 'query': q)
else:
# if the query is empty, render the 'search_form html' template again.
# display an error message in that template. So, pass a template variable.
# 'search_form html' will check for the 'error' variable
return render(request, 'assignments/search_form.html', {'error': True})
This was the FAILED TEMPLATE CODE 'search_results.html
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Results</h1>
<p>You searched for: <strong>{{ query }}</strong></p>
{% if AssignmentsResults %}
<ul>
{% for assignments in AssignmentsResults %}
<li>
{{ assignments.id }}, {{ assignments.name }}
</li>
{% endfor %}
</ul>
<p> These are the Products attached to the Assignment.</p>
{% if ProductsResults %}
<ul>
{% for products in ProductsResults %}
<li>
{{ products.assignment }}, {{ products.name }}
</li>
{% endfor %}
</ul>
{% else %}
<p> No products for this assignment exist.</p>
{% endif %}
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
{% endblock content %}
I have created the project by following 'Build a website with Django 2, updated for Django 2.2' by Nigel George. I have looked at several youtube instructional videos and read questions on stackoverflow. (These are only a couple.)
How to combine two or more querysets in a Django view?
Displaying a series of inline forms for a queryset of Django models
Django: Add queryset to inlineformsets
Django nested QuerySets
InlineFormSet with queryset of different model
However, none of them have been able to help me with my problem of presenting 2 separate queryset results on one form.
I'd certainly appreciate any suggestions and help provided.
Thanks
Okay, let's see. If you just want to display the information that it seems to be intended in search_results.html, I suggest you to refactor a little bit your query as follows.
(I will try to clean out the weird things (for example having two consecutive return statements) as much as I can to illustrate my point)
views.py:
from django.shortcuts import render, redirect
from django.urls import reverse
def search(request):
q = request.GET.get('q', None)
if q:
assignments_qs = Assignments.objects.filter(id__icontains=q) \
.prefetch_related('productsfor_assignment')
context_data = {'assignments': assignments_qs}
return render(request, 'assignments/search_results.html', context_data)
else:
return redirect(reverse('search_form', kwargs={'error': True}))
def search_form(request, error=False):
return render(request, 'assignments/search_form.html', {'error': error})
search_results.html
{% if assignments %}
<ul>
{% for assignment in assignments %}
<li>
{{ assignment.id }}, {{ assignment.name }}
</li>
{% if assignment.productsfor_assignment.exists %}
<p> These are the Products attached to the Assignment.</p>
<ul>
{% for product in assignment.productsfor_assignment.all %}
<li>
{{ product.assignment }}, {{ product.name }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
I think this is the best and the most similar way to achieve what you want considering what you currently have.