ForeignKey don't show data - python

When I try to use foreignKey, html don't response
Models.py
class Home(models.Model):
book = models.ForeignKey(Book, verbose_name=(
"book"), on_delete=models.CASCADE, related_name="book")
Views.py
def main(request):
posts = Home.objects.all()
return render(request, 'home/home-page.html', {'posts': posts})
HTML
{% for post in posts %}
{% for book in post.book.all %}
{{ book }}
{% endfor %}
{% endfor %}
What going wrong?

all doesn't make any sense here, with a one to many relationship home only has one book, a book has many homes
so the inner for loop isn't needed, you can just use post.book
{% for post in posts %}
{{ post.book }}
{% endfor %}

Related

For if Loop ManyToMany Field Django

How can I query a manytomanyfield in a Django template? For example,
this if statement doesn't work, but this shows what I'd like to do:
Model:
class Product(models.Model):
Category = models.ManyToManyField(Category)
Template:
{% for p in Product %}
{% if p.Category_id == 6 %}
{{p.id}}
{% endif %}
{% endfor %}
I think it's better to filter your queryset in views.py as
products = Product.objects.filter(Category__id=6)
then loop through that queryset in template
{% for p in products %}
{{p.id}}
{% endfor %}
I don't know the actual use case. You haven't posted the view. Assuming in django template products is the queryset. e.g products= Product.objects.all(). This is how you will detect the Category instance with id=6 for all the products in django template.
{% for p in products %}
{% for category in p.Category.all %}
{% if category.id == 6 %}
{{p.id}}
{% endif %}
{% endfor %}
{% endfor %}

How to display one set of data between two models?

I have Model Question and Answer.
What I want to accomplish is to be able to display it in the template in a way that shows like this. I would like to know a way to accomplish this. I'm trying my best to not let it loop the whole data in a model but rather one data at a time. I'm trying to make a qna data and make it display on a template. so having all the Questio data displayed before Answer data is not what I want. It has to be one by one for these two models. I'm getting kinda close...but I stil can't figure out how to accomplish this. Any help or advice would be greatly appreciated. Thank you in advance.
Q.title
Q.body
A.body
Q.title
Q.body
A.body
Q.title
Q.body
A.body
modesl.py
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Question(models.Model):
title= models.CharField(max_length= 100)
body= models.TextField()
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(User, on_delete= models.CASCADE)
def __str__(self):
return self.title
class Answer(models.Model):
body= models.TextField()
question= models.ForeignKey(Question, on_delete= models.CASCADE)
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(User, on_delete= models.CASCADE)
def __str__(self):
return self.body
qna.html template
{% extends "info/base.html" %}
{% block content %}
{% for question in questions %}
<h1> Q</h1>
<h3> {{ question.title }} </h3>
{% for answer in answers %}
<h1> A </h1>
<h3> {{ answer.body }}</h3>
{% endfor %}
{% endfor %}
{% endblock content %}
views.py
from django.shortcuts import render
from .models import Question, Answer
def qna(request):
context= {
'questions': Question.objects.all(),
'answers': Answer.objects.all(),
}
return render(request, 'qna/qna.html', context)
As Answer model has relation of ForeignKey with question you can directly access question model fields in reverse.Replace your code in html like below and check if same works for you.
{% extends "info/base.html" %}
{% block content %}
{% for answer in answers %}
<h1> Question:</h1>
<h3> title: {{ answer.question.title }} </h3>
<h3> body: {{ answer.question.body }} </h3>
<h1> Answer: </h1><h3> {{ answer.body }} </h3>
{% endfor %}
{% endblock content %}
Add related_name to model Answer that has ForeignKey with Question:
question= models.ForeignKey(Question, on_delete= models.CASCADE, related_name='my_answes')
in HTML file replace the second loop with :
{% for answer in question.my_answes.all %}
<h1> A </h1>
<h3> {{ answer.body }}</h3>
<hr>
{% endfor %}

Django Check if User Is in Many to Many User Field (template)

I have a model:
class Projects(models.Model):
name = models.CharField(max_length=200)
users = models.ManyToManyField(User)
As you can see, the model contains a ManytoMany field with User model.
In my template, I want to check if the current authenticated user is in the Projects users field that was passed to the template:
#login_required
def index(request):
projects = Projects.objects.all()
context = {
'projects' : projects
}
return render(request,'app/index.html',context)
The template code will look something like this:
{% for project in projects %}
{% if user is in project.user %} {% endif %}
{% endfor %}
Any help will be appreciated!
Almost:
{% for project in projects %}
{% if user in project.users.all %}
{% endif %}
{% endfor %}

how to get a list of questions posted by followed users

Friends, I am trying to implement a question answer site in which a logged in user gets a list of questions and answers asked by the users he follows.
I am using django-friendship to implement user follows. I want to know how we can fetch all the questions posted by the users whom the current user follows.
I have tried the following but doesn't work.
views.py
def index(request):
if request.session.get('current_user'):
questions = []
users = Follow.objects.following(request.user)
i = 0
while i < len(users):
posts = Question.objects.filter(user=users[i])
questions.append(posts)
i = i + 1
return render(request, "welcome/index.html",locals())
Here's my template
welcome/index.html
{% extends "layout.html" %}
{% block content %}
{% for q in questions %}
{{ q.title }}
{% endfor %}
{% endblock %}
You can fetch all questions without looping
views.py
def index(request):
if request.session.get('current_user'):
users = Follow.objects.following(request.user)
questions = Question.objects.filter(user__in=users)
return render(request, "welcome/index.html",locals())
template
{% extends "layout.html" %}
{% block content %}
{% for q in questions %}
{{ q.title }}
{% endfor %}
{% endblock %}
posts is a queryset. Thus, questions is a list of querysets and, in your template, you are not iterating over Question instances, but querysets that do NOT have a title attribute. You can try in your view:
questions.extend(posts) # not: append
in order to obtain an actual list of Question instances. Or, you can change your template:
{% for qs in questions %}
{% for q in qs %}
{{ q.title }}
{% endfor %}
{% endfor %}

Django - Retrieve Data for 2 Separate Querysets On One Page

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.

Categories