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

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

Related

Django filter and count in template tag

I'm trying to filter and count a specific QuerySet in the template with Django template engine. Cant get it to work. The film_list is the context and film is the table and language is a field. Any tips on how to use filter and count at the same time in the template engine? Or should I solve it in another way?
{% if filmlist.film.language == "danish" %}
{{ film_list.all.count }}
{% endif %}
View
class FilmListView(LoginRequiredMixin, ListView):
paginate_by = 150
model = Film
context_object_name = 'film_list'
template_name = 'movies/movie_list.html'
You have to iterate over your context to get each object like this
{% for item in filmlist %}
{% if item.language == "danish" %}
{{ film_list.count }}
{% endif %}
{% endfor %}

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

ForeignKey don't show data

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

How to make generic ListView only show user's listing?

I'm new to Django and I'm utilizing class-based views for the first time. I want to use the generic ListView to show a list of "tables" owned by a user. And so far I've gotten it to display ALL the tables in the database. But I only want it to show tables for the logged in user.
this is what my view looks like:
from django.shortcuts import render
from django.http import HttpResponse
from django.views import generic
from vtables.models import Vtable
class TableListView(generic.ListView):
model = Vtable
context_object_name = 'table_list'
def get_context_data(self, **kwargs):
context = super(TableListView, self).get_context_data(**kwargs)
return context
And this is what my model looks like:
from django.db import models
from django.contrib.auth.models import User
class Vtable(models.Model):
user = models.ForeignKey(User)
table_name = models.CharField(max_length=200)
added_date = models.DateTimeField('date added')
class Vdata(models.Model):
table_id = models.ForeignKey(Vtable)
table_pk = models.IntegerField()
column_1 = models.CharField(max_length=200)
column_2 = models.CharField(max_length=200)
added_date = models.DateTimeField('date added')
I'll admit, I'm not sure what this line is doing:
context = super(TableListView, self).get_context_data(**kwargs)
But I suspect this is what I need to change? Or do I have to go into my template and do an if statement there? Maybe something like: {% if request.user == vtable.user %}?
EDIT: here is my template:
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
{% if request.user.is_authenticated %}
<img src="{{ request.user.profile.profile_image_url }}"/>
Logout
{% if request.user.first_name or request.user.last_name %}
{{ request.user.first_name }} {{ request.user.last_name }}
{% else %}
{{ request.user.username }}
{% endif %}
{% if request.user.profile.account_verified %}
(verified)
{% else %}
(unverified)
{% endif %}
<h1>Tables</h1>
<ul>
{% for vtable in table_list %}
<li>{{ vtable.user }}, {{ vtable.table_name }}</li>
{% endfor %}
</ul>
{% else %}
Login
{% endif %}
{% endblock %}
perhaps, overriding get_queryset():
def get_queryset(self):
return self.model.objects.filter(user=self.request.user)

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