How to combine any fields in one in Django filters - django

I wonder how you combine search from multiple fields into one. The fields would be textoQuestao, perguntaQuestao, aOpcao, bOpcao, cOpcao, eOpcao, eOpcao.
I would like all of these fields to be combined into one called texto and to search all selected fields.
filters.py
class FiltroQuestoes(django_filters.FilterSet):
texto =
class Meta:
model = Questao
fields = ['textoQuestao','perguntaQuestao','aOpcao','bOpcao','cOpcao','dOpcao','eOpcao','idProva','idQuestao','idCategoria']
views.py
def FiltroDeQuestoesView(request):
qs = filter(request)
context = {
'queryset': qs,
'categorias': Categoria.objects.all(),
'provas': Prova.objects.all()
}
return render(request, "polls/pesquisa.html", context)
def filter(request):
qs = Questao.objects.all()
categorias = Categoria.objects.all()
prova = request.GET.get('prova')
provas = Prova.objects.all()
questao = request.GET.get('questao')
categoria = request.GET.get('categoria')
return qs
search.html
{% block content %}
<form method="get">
<div class="well">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.texto.label_tag }}
{% render_field filter.form.texto class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.idProva.label_tag }}
{% render_field filter.form.idProva class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.idQuestao.label_tag }}
{% render_field filter.form.idQuestao class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.idCategoria.label_tag }}
{% render_field filter.form.idCategoria class="form-control" %}
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
{% endblock %}

I would suggest you should go with elasticsearch for this.
But you can use django Q objects to do OR query
qs = Questao.objects.filter(Q(textoQuestao__icontains=query_string)| Q(perguntaQuestao__icontains=query_string)|...

Related

Problems with a backend part of search line in Django

who can explain me why my SearchView doesn't work. I have some code like this.It doesn't show me any mistakes, but it doesn't work. The page is clear. Seems like it doesn't see the input.
search.html
<div class="justify-content-center mb-3">
<div class="row">
<div class="col-md-8 offset-2">
<form action="{% url 'search' %}" method="get">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search..." />
<div class="input-group-append">
<button class="btn btn-dark" type="submit" id="button-addon2">Search</button>
</div>
</div>
</form>
</div>
</div>
</div>
search/urls.py
path('search/', SearchView.as_view(), name='search')
search/views.py
class SearchView(ListView):
model = Question
template_name = 'forum/question_list.html'
def get_queryset(self):
query = self.request.GET.get("q")
object_list = Question.objects.filter(
Q(title__icontains=query) | Q(detail__icontains=query)
)
return object_list
forum/question_list.html
{% extends 'main/base.html' %}
{% block content %}
{% for question in object_list %}
<div class="card mb-3">
<div class="card-body">
<h4 class="card-title">{{ question.title }}</h4>
<p class="card-text">{{ question.detail }}</p>
<p>
{{ question.user.username }}
5 answers
10 comments
</p>
</div>
</div>
{% endfor %}
{% endblock %}

My for loop does not work as expected - Data does not show up in my django template

I am trying to use a for loop in my Django template to show the data stored in the models of a table but for some reason , the data does not show up in the template.
Views.py
def add_part(request):
parts = Parts.objects.all()
context = {
"parts": parts
}
return render(request, 'admintemplate/add_parts_template.html', context)
def add_part_save(request):
if request.method != "POST":
messages.error(request, "Method Not Allowed!")
return redirect('add_part')
else:
part_name = request.POST.get('part_name')
part_type = request.POST.get('part_type')
supplier_id = request.POST.get('suppliers')
suppliers = Suppliers.objects.get(id=supplier_id)
try:
part = Parts(part_name=part_name, part_type=part_type, supplier_id=supplier)
part.save()
messages.success(request, "Part Added Successfully!")
return redirect('add_part')
except:
messages.error(request, "Failed to Add Part!")
return redirect('add_part')
models.py
The parts and the services model are exactly the same with different column names, so I think the functionality for both should be the same.
Suppliers models
class Suppliers(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
Parts model
class Parts(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
part_type = models.CharField(max_length=20)
supplier_id = models.ForeignKey(Suppliers, on_delete=models.CASCADE)
Services model
class Services(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
service_type = models.CharField(max_length=20)
supplier_id = models.ForeignKey(Suppliers, on_delete=models.CASCADE)
Part template
{% extends 'admintemplate/base_template.html' %}
{% block page_title %}
Add Parts
{% endblock page_title %}
{% block main_content %}
{% load static %}
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<!-- general form elements -->
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Add Parts</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
<form role="form" method="POST" action="{% url 'add_part_save' %}">
{% csrf_token %}
{% comment %} Display Messages {% endcomment %}
{% if messages %}
<div class="form-group">
<div class="col-12">
{% for message in messages %}
{% if message.tags == "error" %}
<div class="alert alert-danger alert-dismissible fade show" role="alert" style="margin-top: 10px;">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% elif message.tags == "success" %}
<div class="alert alert-success alert-dismissible fade show" role="alert" style="margin-top: 10px;">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="card-body">
<div class="form-group">
<label>Part Name </label>
<input type="text" class="form-control" name="part_name" placeholder="Part Name">
</div>
<div class="form-group">
<label>Part Type </label>
<input type="text" class="form-control" name="part_type" placeholder="Part Type">
</div>
<div class="form-group">
<label>Supplier Name</label>
<select class="form-control" name="suppliers">
{% for supplier in suppliers %}
<option value="{{ supplier.id }}">{{ supplier.name }}</option>
{% endfor %}
</select>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">Add Part</button>
</div>
</form>
</div>
<!-- /.card -->
</div>
</div>
</div><!-- /.container-fluid -->
</section>
{% endblock main_content %}
Now the services in parts template does not show up at all. There is no choices on the form. But, for the add services template, it does populate. I have no idea why this happens because I have used the exact same code for both templates.
Changing the view to this solved the issue
def add_part(request):
parts = Parts.objects.all()
context = {
"suppliers": suppliers
}
return render(request, 'admintemplate/add_parts_template.html', context)

Sort by ascending and descending using django-filter

I have the following code for few filterings:
from .models import ProductLaptop
import django_filters
class ProductLaptopFilter(django_filters.FilterSet):
laptops_name = django_filters.CharFilter(lookup_expr='icontains')
laptops_price = django_filters.NumberFilter()
laptops_price__gt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='gt')
laptops_price__lt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='lt')
class Meta:
model = ProductLaptop
fields = ['laptops_name', 'laptops_price', 'brand_name']
The html codes for this:
{% load widget_tweaks %}
{% block content %}
<form method="get">
<div class="well">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_name.label_tag }}
{% render_field filter.form.laptops_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price.label_tag }}
{% render_field filter.form.laptops_price class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.brand_name.label_tag }}
{% render_field filter.form.brand_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__gt.label_tag }}
{% render_field filter.form.laptops_price__gt class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__lt.label_tag }}
{% render_field filter.form.laptops_price__lt class="form-control" %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
Which gives me a view like below:
Here I want to add an option where people can sort the items in ascending and descending order.
Can anyone give me some suggestions how can I implement this?
For that, you can use OrderingFilter from django-filter. Create this filter in your FilterSet class and provide all fields that should be enabled for ordering.

Django Form doesn't Get Correct Columns

I have struggled with this for about an hour and cannot seem to find a solution.
I have a django model that I have created form with using ModelForm. The form is inside a view and I want to manipulate the form variables before submitting to the database. The problem is that I cannot seem to get the correct columns to reference from the database for the form. Instead it looks like it is referencing the columns from another related table. Any suggestions?
Models
class RoutinePlans(models.Model):
routine = models.ForeignKey(Routines, on_delete='CASCADE')
exercise = models.ForeignKey(WeightExercises, on_delete='PROTECT')
set = models.IntegerField()
set_type = models.ForeignKey(SetType, on_delete='PROTECT')
reps = models.IntegerField()
day = models.IntegerField()
week = models.IntegerField()
def __str__(self):
return self.routine.name
class Routines(models.Model):
name = models.CharField(max_length=50)
level = models.ForeignKey(RoutineLevels, on_delete='PROTECT')
creator = models.ForeignKey(User, on_delete='CASCADE')
status = models.TextField(max_length=50)
description = models.TextField(max_length=255, null='TRUE', default=None)
def __str__(self):
return self.name
Forms
class PlanForm(forms.ModelForm):
DAY_CHOICES = (('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'))
day = forms.ChoiceField(widget=forms.Select, choices=DAY_CHOICES)
class Meta:
model = RoutinePlans
exclude = ['routine']
Views
#not sure if this view would have anything to do with the error but figured I would include it to give the full perspective
def createplan(request):
form = forms.CreatePlan()
if request.method == 'POST':
form = forms.CreatePlan(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.name = request.POST['name']
obj.creator_id = request.user.id
obj.status = "DRAFT"
obj.save()
return redirect('fitnessmanagement:editplan', id=obj.pk)
else:
print('error form invalid')
variables = {'form': form}
return render(request, template_name='createplan.html', context=variables)
def editplan(request, routine_id):
form = forms.PlanForm()
routine_name = Routines.objects.get(id=routine_id).name
if request.method == 'POST':
form = forms.PlanForm(data=request.POST)
if form.is_valid():
obj = form.save(commit=False)
#this is where I want to put obj.routine but the form will only pull fields from the Routines model and not the Routine Plans
obj.save()
return redirect('fitnessmanagement:editplan', routine_id=routine_id)
# variables to populate plan
plan = RoutinePlans.objects.filter(routine_id=routine_id)
plan_weeks = RoutinePlans.objects.filter(routine_id=routine_id).values('week').distinct()
plan_dayss = RoutinePlans.objects.filter(routine_id=routine_id).values('day', 'week').distinct()
plan_excercise_name = RoutinePlans.objects.filter(routine_id=routine_id).values('day', 'week', 'exercise_id', 'set_type_id').distinct()
plan_excercise = RoutinePlans.objects.filter(routine_id=routine_id).prefetch_related('exercise')
names = WeightExercises.objects.all()
setDetails = RoutinePlans.objects.filter(routine_id=routine_id).values('set', 'reps', 'day', 'week', 'exercise', 'set_type')
set_type = SetType.objects.all()
# end variables to populate plan
variables = {'form': form,
'id': routine_id,
'routine_name':routine_name,
'plan': plan,
'plan_weeks': plan_weeks,
'plan_exercises': plan_excercise,
'plan_exercise_name': plan_excercise_name,
'plan_days': plan_dayss,
'setDetails': setDetails,
'names': names,
'set_type': set_type,
}
return render(request, template_name='editplan.html',context=variables)
Templates
{% extends 'layout/master-layout.html' %}
{% load static %}
{% block content %}
<section id="content">
<!--start container-->
<div class="container">
<div class="row">
<div class="col s12 m6 l4">
<div class="card-panel">
<h4 class="header2">Add Workout</h4>
<div class="row">
<form class="col s12" method="POST">
{% csrf_token %}
<div class="row">
<div class="input-field col s12">
{{ form.week }}
<label for="weekNumber">Week Number</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.day }}
<label for="dayNumber">Day Number</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.exercise }}
<label for="exercise_name">Exercise Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.set_type }}
<label for="set_type">Set Type</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.set }}
<label for="set">Set Number</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.reps }}
<label for="reps">Rep Number</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.routine }}
<label for="routine">Routine</label>
</div>
</div>
<div class="row">
<div class="row">
<div class="input-field col s12">
<button class="btn waves-effect waves-light right trusique-red"
type="submit" name="submit">Add Workout
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col s12 m6 l8">
<div class="card-panel">
<h4>Editing: {{ routine_name }}</h4>
<ul class="collapsible" data-collapsible="expandable">
{% for plan_week in plan_weeks %}
<li>
<div class="collapsible-header"><i
class="material-icons">whatshot</i>{{ plan_week.week }}- Week
</div>
<div class="collapsible-body">
<ul class="collapsible" data-collapsible="expandable">
{% for plan_day in plan_days %}
{% if plan_day.week == plan_week.week %}
<li>
<div class="collapsible-header">{{ plan_day.day }}- day</div>
<!--collapsible workout name body -->
<div class="collapsible-body">
<ul class="collapsible" data-collapsible="expandable">
<!--begin workout name list-->
{% for plan_exercise in plan_exercise_name %}
{% for n in names %}
{% for s in set_type %}
{% if plan_day.day == plan_exercise.day and plan_week.week == plan_exercise.week and plan_exercise.exercise_id == n.id and plan_exercise.set_type_id == s.id%}
<li>
<div class="collapsible-header">{{ n.exercise_name }}-
Excercise {{ s.type }}
</div>
<div class="collapsible-body">
{% for setDetail in setDetails|dictsort:"set" %}
{# <p> setdetails exerceice {{ setDetail.exercise }}#}
{# plan excerice {{ plan_exercise.id }}</p>#}
{% if plan_day.day == setDetail.day and plan_week.week == setDetail.week and plan_exercise.exercise_id == setDetail.exercise and s.id == setDetail.set_type %}
<div class="row">
<div class="col s12 m4 l4">
Set {{ setDetail.set }}
</div>
<div class="col s12 m4 l4">
: {{ setDetail.reps }}Reps
</div>
</div>
{% endif %}
{% endfor %}
</div>
</li>
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
</ul>
</div>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
<!--end container-->
</section>
<!-- END CONTENT -->
{% endblock %}

Django autopopulate entire form with model data based of single choice field

I am trying to make a modelform that populates all fields based on a single select field. Basically when the user selects a value from a dropdown it would then populate the rest of the fields based on data from a database.
models.py:
class Commands(models.Model):
command_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
command_prefix = models.TextField()
command = models.TextField()
args = models.TextField()
shell = models.TextField()
role = models.ForeignKey('Roles', models.DO_NOTHING)
os = models.ForeignKey('Operatingsystems', models.DO_NOTHING)
job_type = models.ForeignKey('Jobtypes', models.DO_NOTHING)
active = models.IntegerField()
views.py:
#verified_email_required
def jobs(request):
return render(request, 'backend/jobs.html', {'form': CommandsForm()})
forms.py:
class CommandsForm(Form):
name = ModelChoiceField(queryset=Commands.objects.filter(active=1).values('name'))
os = CharField(required=True, disabled=True)
command_prefix = CharField(required=True, disabled=True)
target = CharField(required=True)
command = CharField(required=True, disabled=True)
args = CharField(required=True, disabled=True)
shell = CharField(required=True, disabled=True)
urls.py
urlpatterns = [
url(r'^$', profile, name='profile'),
url(r'^jobs/$', jobs, name='jobs'),
url(r'^patchreport/$', patchreport, name='patchreport'),
url(r'^prtbl/$', PatchReportTable.as_view(), name='patchreptbl')
]
jobs.html
{% extends "backend/base.html" %}
{% load staticfiles %}
{% load widget_tweaks %}
{% block title %}
{{block.super}}Jobs
{% endblock %}
{% block content %}
<form id="jobs_form" class="form-horizontal text-center" method="post" action="{% url 'jobs' %}">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form-group">
{{ form.name.errors }}
<label for="{{ form.name.id_for_label }}" class="col-sm-2 control-label">Name</label>
<div class="col-sm-8">
{{ form.name|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.os.id_for_label }}" class="col-sm-2 control-label">Os</label>
<div class="col-sm-8">
{{ form.os|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.command_prefix.id_for_label }}" class="col-sm-2 control-label">Command prefix</label>
<div class="col-sm-8">
{{ form.command_prefix|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.target.id_for_label }}" class="col-sm-2 control-label">Target</label>
<div class="col-sm-8">
{{ form.target|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.command.id_for_label }}" class="col-sm-2 control-label">Command</label>
<div class="col-sm-8">
{{ form.command|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.args.id_for_label }}" class="col-sm-2 control-label">Args</label>
<div class="col-sm-8">
{{ form.args|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<label for="{{ form.shell.id_for_label }}" class="col-sm-2 control-label">Shell</label>
<div class="col-sm-8">
{{ form.shell|add_class:"form-control" }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<button type="submit" class="btn btn-default" name="submit">Submit</button>
</div>
</div>
</form>
<script type="text/javascript" src="{% static "js/jobs.js" %}"></script>
{% endblock %}
To be honest, I am unsure of how to accomplish this with Django's ModelForms. Currently I took Michael Platt's advice and am auto-populating the fields with javascript on change event in a javascript file called jobs.js. I have to believe there is a way to accomplish the same thing by populating the entire form from the database directly, or via something like a RESTful api generated by TastyPie with an ajax call.
If you aren't too turned off by the concept of using javascript, you could use a .change() event for your particular select field. So it would look something like this:
$(document).ready(function(){
$("#id_name").change(function() {
// Find your different fields you want to populate and set the values here.
// Example would be
if ($("#id_name").val() == "Some value") {
$("#id_command_prefix").val("Whatever you want to populate with.")
}
});
});