I am using django-filter==2.1.0 for implementing search filter. I already implement it. But now i need to search by clicking checkbox not by search button. My codes are given below:
models.py
class Book(models.Model):
name = models.CharField(max_length=100)
publication = models.ForeignKey(Publication, on_delete=models.CASCADE)
filters.py
class BookFilter(django_filters.FilterSet):
publication = django_filters.ModelMultipleChoiceFilter(queryset=Publication.objects.all(),
widget= forms.CheckboxSelectMultiple)
class Meta:
model = Book
fields = ['publication']
views.py
def test_view(request):
book_list = Book.objects.all()
book_filter = BookFilter(request.GET, queryset=book_list)
temp = book_filter.form
return render(request, 'test.html', {'filter': book_filter})
template
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
<form method="get">
{% for choice in filter.form.publication %}
<label>
{{ choice.tag }}
<span class="max-content-width">{{ choice.choice_label }}</span>
</label>
{% endfor %}
<button type="submit">Search</button>
</form>
<ul>
{% for book in filter.qs %}
<li>{{ book.name }}</li>
{% endfor %}
</ul>
{% endblock %}
It's working properly. But i want to add widget = forms.CheckboxInput(attrs={'onclick': 'this.form.submit();'}) in my filters.py for checkbox input. I don't understand how can i add another widget. Please help me to solve this problem.
Create a widget, write JavaScript script and use Media metaclass on widget to use it. After this just use your widget on your checkbox field.
Related
Trying to get the table name in django, I need it to display the detailview correctly via if statemnet.
I have such a view to display
class Home(ListView):
template_name = 'home.html'
def get_queryset(self):
qs1 = Book.objects.all()
qs2 = CD.objects.all()
qs3 = Film.objects.all()
queryset = sorted(list(chain(qs1, qs2, qs3)), key=operator.attrgetter('title'))
return queryset
and it returns to me this
[<CD: Music1>, <CD: Music2>, <Book: Some books>]
How can I get "CD" or "Book" in this template
{% block content %}
<div class="row">
{% for object in object_list %}
<div class="col-md-3">
<div class="card card-product-grid">
<img src="{{ object.image.url }}">
{{ object.title }}
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
At the same time, if it's a bad idea to display detailview and listview and it's done differently, I'd appreciate it if you'd let me know
I tried different ways of displaying object.key in a loop but it didn't work very well. And other queryset queries.
I've been down the list(chain(ob1, ob2, .. obn) route. It proved highly tedious from a standpoint of code maintainability and complexity. Django Polymorphic is the way to go here.
from polymorphic.models import PolymorphicModel
class Product(PolymorphicModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='products')
title = models.CharField(max_length=100)
slug = ...
... more fields all products share ex: price
def __str__(self):
return str(self.title)
#property
def model_name(self):
return self._meta.model_name
class Cd(Product):
<model fields for CD model>
class Book(Product):
<model fields for book model>
class Film(Product):
<model fields for film model>
Then:
Product.objects.all()
Will return the instances of all CD, Book and Film objects.
In your template, you can use the property model_name to check if the object is a certain type of model.
{% block content %}
<div class="row">
{% for object in object_list %}
{% if object.model_name == 'book' %}
<div class="col-md-3">
<div class="card card-product-grid">
<img src="{{ object.image.url }}">
{{ object.title }}
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock content %}
You can obtain this with the .verbose_name attribute [Django-doc] of the model options, so my_object._meta.verbose_name. There is however a problem here: you can not access variables that start with an underscore, since these are "protected" or "private".
A solution might be to work with a template filter. You can define a templatetags directory:
app_name/
__init__.py
models.py
templatetags/
__init__.py
model_utils.py
views.py
where you create the files in boldface. In model_utils, you can construct a filter with:
from django import template
register = template.Library()
#register.filter
def modelname(value):
return value._meta.verbose_name
then we can use these in the template with:
{% load model_utils %}
{% for object in object_list %}
…
{{ object|modelname }}
{% endfor %}
hello iam trying to make Dropdown Menu in Navbar with querysets. I was trying to make it with two querysets send to html template ( "stages","questions") that are related to each other by key (id , stage_id), but i cant figured out why forloops cant work together. My second try was with passing data in json to javascript and make it with js QuerySelector, but django querysets are not JSON serializable. Any suggestions how to make it please ?
views.py
def edit_pages(request, gameid):
stages = Stage.objects.filter(game_id=gameid)
print(stages)
questions = []
for st in stages:
questions = chain(questions,Question.objects.filter(stage_id=st.id))
print(questions)
return render(request, "homeSuperuser/edit_pages.html",{'stages': stages, 'questions': questions})
html
<body>
<div class="topnav">
{% for st in stages %}
<div class="dropdown">
<button class="dropbtn">{{st.stage_name}}</button>
<div class="dropdown-content">
{% for qs in questions %}
{% if qs.stage_id == st.id %}
{{qs.question_name}}
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</body>
Define a model method as follows
class Stage(models.Model):
name = models.CharField(max_length=128)
def get_questions(self):
return Question.objects.filter(stage=self)
def __str__(self):
return str(self.name)
class Question(models.Model):
stage = models.ForeignKey(Stage, on_delete=models.PROTECT, related_name="questions")
name = models.CharField(max_length=128)
def __str__(self):
return str(self.name)
Now you can loop them in the template as follows
{% for st in stages %}
<div class="dropdown">
<button class="dropbtn">{{st.name}}</button>
<div class="dropdown-content">
{% for qs in st.get_questions %}
{{qs.name}}
{% endfor %}
</div>
</div>
{% endfor %}
I have a model called Section and a model called SectionInfo. Section has one field and that's name. A user will create a section by giving it a name. SectionInfo has a foreign key section_name which links it to the Section model. I have a few other fields inside SectionInfo such as things like detail, date_created, etc. What I am trying to accomplish here is using a for loop to display section names that have already been created inside or above some cards that I have set up in an html template. Then I want to use a nested loop to gather the data that is tied to that section name which is what the user inputs in for the SectionInfo model. I am able to display the section names correctly, but the issue im having is in the loop inside that loop. The same detail link is being displayed in every section that was made. Information should only be displayed in the chosen section for which it was made.
Here is a bit of code to help you understand what I am trying to accomplish.
Template file:
{% extends "base.html" %}
{% load bootstrap5 %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
{% for i in object %}
{{ i.name}}
<div class="row">
<div class="col-sm-4">
<div class="card">
<div class="card-body">
{% for ii in object_2 %}
Details
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock content %}
Here is what I am getting displayed
whats being displayed
Here is the view that's being used
def section_info_detail(request, pk):
object = get_object_or_404(Section, id=pk)
object_2 = get_object_or_404(SectionInfo, id=pk)
context = {
'object': object,
'object_2':object_2,
}
return render(request, 'manufacturing/section_info_detail.html', context)
Models.py:
class Section(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class SectionInfo(models.Model):
section_name = models.ForeignKey(Section, on_delete=models.CASCADE)
detail = models.CharField(max_length=50)
text = models.TextField(max_length=2000)
date_created = models.DateField('Date created', auto_now_add=True)
date_updated = models.DateField('Date updated', auto_now=True)
Forms.py:
class SectionNameForm(forms.ModelForm):
class Meta:
model = Section
fields = [
'name',
]
class SectionInfoForm(forms.ModelForm):
class Meta:
model = SectionInfo
fields = [
'section_name',
'detail',
'text',
]
If any other information is needed, do tell.
<div class="row">
{% for object in object_list %}
<div class="col-sm-4">
<div class="card">
<div class="card-header">
<h1><strong>{{ object.name }}</strong></h1>
<hr>
</div>
<div class="card-body">
<div class="row">
{% for info in object.section_infos.all %}
<ul id="list">
<li>{{ info.date_created }}</li> |
<li>{{ info.detail|truncatechars:20 }}</li>
<hr>
</ul>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
This did it for me. So basically what my problem was I was not drilling down far enough to get the data that I needed to be displayed from the template. Also I had changed some things up in my models and had created a manyTomany and through field
I want to display 1 Parent Field with associated Child and further there Childs
I have a Model
class GrandParent(models.Model):
name= models.CharField(max_length=50)
....
class Parent(models.Model):
parent = models.ForeignKey(GrandParent, on_delete=models.CASCADE)
name= models.CharField(max_length=50)
....
class Child(models.Models):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
name= models.CharField(max_length=50)
...
I am able to render objects from Grand Parent But I m unable to link further Parent Class objects and Child class objects in templates
This approach I used in views.py
def list(request):
object_list = GrandParent.published.all()
...
return render('app/list.html')
def detail(request, post,):
post = get_object_or_404(GrandParent, slug=post,
status='published')
return render(request, 'app/detail.html',
{'post' : post,
...
})
Now how to link further Classes in Same Detail View But Associated with there Parent Classes using Foreign Key. I'm following Django docs but they only giving max 2 examples using python shell with just One subclass I m confused How to implement there in this structure. Or anyone have already developed any project specifically with this type of models so please share any link of repo or something, would be wonderful.
#list.html
{% extends "_base.html" %}
{% block title %} mysite{% endblock %}
{% block content %}
<h2>Content </h2>
<ul>
{% for post in object_list %}
<a href="{{ post.get_absolute_url }}">
<li>{{ post.name}}</li></a>
{% endfor %}
</ul>
{% endblock %}
#detail.html
{% extends "_base.html" %}
{% block title %} freeStreams {% endblock %}
{% block content %}
<div class="card-body">
<h1 class="card-title">{{ post.title }}</h1>
</div>
{% endblock %}
You can access from one to many in view template by for loop all child of it. In your case, with GrandParent by post.parent_set.all(). For Child by parent.child_set.all(). You can try first in terminal for check you have correct database and relation.
Add it inside block content
detail.html
{% for parent in post.parent_set.all() %}
<h1 class="card-title">{{ parent.name }}</h1>
{% for child in parent.child_set.all() %}
<h2 class="card-title">{{ child.name }}</h2>
{% endfor %}
{% 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.