I have this view:
class DamageListCriteria(TemplateView):
template_name = "damage/damagelist_criteria.html"
def get(self, request):
form = DamageListCriteriaForm()
general = General.objects.get(pk=1)
args = {
'form': form,
'general': general
}
return render(request, self.template_name, args)
def post(self, request):
general = General.objects.get(pk=1)
form = DamageListCriteriaForm(request.POST)
form.non_field_errors()
if form.is_valid():
fromdate = request.POST.get('fromdate')
fdate = datetime.strptime(fromdate, '%d/%m/%Y')
fdate = datetime.combine(fdate, datetime.min.time(), tzinfo=pytz.UTC)
print('fdate ', fdate)
todate = form.cleaned_data['todate']
#tdate = datetime.strptime(todate, '%d/%m/%Y') + timedelta(days=1)
tdate = datetime.strptime(todate, '%d/%m/%Y')
tdate = datetime.combine(tdate, datetime.max.time(), tzinfo=pytz.UTC)
print('tdate ', tdate)
d_list = Damage.objects.filter(entry_date__range=(fdate, tdate))
paginator = Paginator(d_list, 1)
page = request.GET.get('page')
try:
damage_list = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
damage_list = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
damage_list = paginator.page(paginator.num_pages)
template = "damage/damagelist_table.html"
form = DamageListForm()
general = General.objects.get(pk=1)
fromdatetext = fdate.strftime('%d/%m/%Y')
todatetext = tdate.strftime('%d/%m/%Y')
args = {
'form': form,
'damage_list': damage_list,
'general': general,
'fromdate': fromdatetext,
'todate': todatetext
}
return render(request, template, args)
else:
print('form is not valid')
print(form.errors)
# form = DamageEntryForm()
args = {'form': form,
'general': general
}
return render(request, self.template_name, args)
I want to get some criteria to make a filtering listing of my database.
It worked this way , until the moment i tried to add pagination.
The url is http://127.0.0.1:8000/damage/damage/list/criteria/
url(r'damage/list/criteria/$', views.DamageListCriteria.as_view(), name="damage-list-criteria"),
Next and Previous don't work because I am still at this url after the
return render(request, template, args)
Can i redirect somehow?
I understand that this might be the wrong way to do the listing. Can you help me , how to do it?
Thanks a lot
Kostas
The easiest thing to do would be not use Django itself but use Django REST framework and reuse its serializer classes along with APIView (or one of its subclasses). Are you in a position to use it or are you constrained?
Related
I want to add pagination to my search results in django. This is my search function form views.py for the relevant (Jobs) module:
def search(request):
queryset_list = Job.objects.order_by('-publishing_date')
if 'keywords'in request.GET:
keywords = request.GET['keywords']
if keywords:
queryset_list = queryset_list.filter(description__icontains=keywords)
if 'state' in request.GET:
state = request.GET['state']
if state:
queryset_list = queryset_list.filter(location__iexact=state)
if 'job_type' in request.GET:
job_type = request.GET['job_type']
if job_type:
queryset_list = queryset_list.filter(job_type__iexact=job_type_choices)
if 'industry' in request.GET:
industry = request.GET['industry']
if industry:
queryset_list = queryset_list.filter(industry__icontains=industry_choices)
if 'salary' in request.GET:
salary = request.GET['salary']
if salary:
queryset_list = queryset_list.filter(salary__lte=salary)
context = {
'location_choices':location_choices,
'salary_choices':salary_choices,
'job_type_choices':job_type_choices,
'industry_choices':industry_choices,
'jobs':queryset_list,
'values':request.GET,
}
return render(request, 'jobs/search.html', context)
This is pagination function from the same file:
def index(request):
jobs = Job.objects.order_by('-publishing_date').filter(is_published=True)
paginator = Paginator(jobs, 6)
page = request.GET.get('page')
paged_jobs = paginator.get_page(page)
context = {
'jobs': paged_jobs
}
return render(request, 'jobs/jobs.html', context)
Both of them work (search returns results and pagination works on listing page) however I want to have pagination too for my search results. I am very new to python and django, and assume there is more elegant way of writing my search function, so please do not hesitate to let me know your thoughts.
I want to add all the amount field during a date range query search. I have an Income Model with date and amount fields among others. And any time a user select between two dates, I want the amount fields of the query results added as total.
Here is what I have tried:
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
listIncome = Income.objects.filter(
description__icontains=searchForm['description'].value(),
date__range=[
searchForm['start_date'].value(),
searchForm['end_date'].value()
]
)
else:
searchForm = IncomeSearchForm()
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
context = {
'searchForm':searchForm,
}
return render(request, 'cashier/search_income_range.html', context)
I am able to get the correct search result but getting the total I don't know how to use the SUM in the above query and pass the total in pagination. So Someone should please help me out. Thanks
from django.db.models import Sum
total_amount = listIncome.aggregate(total=Sum('amount'))
where listIncome is your queryset
Edit:
You should pass queryset in pagination with filtered queryset if any filter you apply.
I changed your written code but you can write this code in a good way.
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
# you can get filter value by your form data
post_data = request.POST
description = post_data['description']
start_date = post_data['start_date']
end_date = post_data['end_date']
else:
# you can get filter value by your query params
query_params = request.GET
description = query_params.get('description')
start_date = query_params.get('start_date')
end_date = query_params.get('end_date')
# Apply filter before pagination
listIncome = listIncome.filter(
description__icontains=description,
date__range=[start_date, end_date]
)
# calculate total_amount
total_amount = listIncome.aggregate(total=Sum('amount'))
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
# you can access total_amount in template by passing in context data
context = {
'searchForm':searchForm,
'total_amount': total_amount
}
return render(request, 'cashier/search_income_range.html', context)
Hello everybody I keep having this problem with my search form in my website. The thing is that, based on the user input, i check if in the database there're some results. But if the input is both in band column and album colum I'd like the user to be redirected to a 'disambiguation' html page. This is my views.py but it doesn't work. Hope someone could help me, thanks!
Views.py
class searchesView(TemplateView):
template_name = "search/searches.html"
def post(self, request, *args, **kwargs):
print('FORM POSTED WITH {}'.format(request.POST['srh']))
srch = request.POST.get('srh')
if srch:
sr = Info.objects.filter(Q(band__icontains=srch))
sd = Info.objects.filter(Q(disco__icontains=srch))
if sr is sd:
return render(self.request, 'search/disambigua.html')
else:
paginator = Paginator(sr, 10)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(self.request, 'search/searches.html', {'sr':sr,
'sd': sd,
'page_obj': page_obj
})
else:
return render(self.request, 'search/searches.html')
Currently, I am using this code to render a page:
return render(request, 'appname/bundles_edit.html', context)
This works fine. However, I would like to send two integers to my path:
path('bundles/<int:bundle_template_number>/<int:bundle_id>/', views.bundles_edit, name='bundles_item'),
How would I insert those two integers in my return render statement?
Edit:
Views Functions:
def bundles(request):
context = {}
if 'bundle_to_edit' in request.POST:
bundle = request.POST['bundle_to_edit']
instance_as_list = bundle.split(',')
template_number = instance_as_list[0]
template_id = instance_as_list[1]
return render(request, 'contractor/bundles_edit.html' + '/' + template_number + '/' + template_id,, context)
return render(request, 'contractor/bundles.html, context)
def bundles_edit(request):
context= {}
return render(request, 'contractor/bundles_edit.html', context)
I know the first return render is wrong, but I am not sure how to do it properly.
Edit 2: Updated code.
def bundles(request):
if 'bundle_to_edit' in request.POST:
bundle = request.POST['bundle_to_edit']
instance_as_list = bundle.split(',')
template_number = instance_as_list[0]
bundle_id = instance_as_list[1]
context['bundle_template_number'] = template_number
context['bundle_id'] = bundle_id
return render(request, 'contractor/bundles_edit.html', context)
return render(request, 'contractor/bundles.html, context)
def bundles_edit(request, bundle_template_number, bundle_id):
context= {}
context['bundle_template_number'] = bundle_template_number
context['bundle_id'] = bundle_id
return render(request, 'contractor/bundles_edit.html', context)
urls.py:
path('bundles/<int:bundle_template_number>/<int:bundle_id>/', views.bundles_edit, name='bundles_item'),
Everything works at this point, it just leaves me with the browser URL as: /contractor/bundles/ instead of /contractor/bundles/1/8/
You can see that your path is good, like they said in the docs :
path('articles/<int:year>/<int:month>/', views.index)
def index(request, year, month):
...
year = Years.objects.get(pk=year)
month = Months.objects.get(pk=month)
return render(request, 'yourtamplate.html', {'year':year, 'month':month})
Is that your idea?
I'm trying to create a confirmation page. User can create orders on one page, then the create_order view validates the forms and send a request with context to another view which is called confirm_order. I think that I would work correct but there is one problem. The first time confirm_order gets request and context which contains data from forms. But when User clicks on confirm in this page, the confirm_view is called without this context so I'm getting error:
> ValidationError at /create-job/ [u'ManagementForm data is missing or
> has been tampered with']
Do you guys know how to send the context second time?
Here are those two views:
def create_order(request):
LanguageLevelFormSet = formset_factory(LanguageLevelForm, extra=5, max_num=5)
language_level_formset = LanguageLevelFormSet(request.POST or None)
job_creation_form = JobCreationForm(request.POST or None, request.FILES or None)
context = {'job_creation_form': job_creation_form,
'formset': language_level_formset}
if request.method == 'POST':
if job_creation_form.is_valid() and language_level_formset.is_valid():
cleaned_data_job_creation_form = job_creation_form.cleaned_data
cleaned_data_language_level_formset = language_level_formset.cleaned_data
context = {
'cleaned_data_job_creation_form': cleaned_data_job_creation_form,
"cleaned_data_language_level_formset": cleaned_data_language_level_formset,
}
mutable = request.POST._mutable # I'm adding parameter 'review' to be able to differ between two different posts in confirm_order view
request.POST._mutable = True
request.POST['review'] = True
request.POST._mutable = mutable
return confirm_order(request, context)
else:
return render(request, 'auth/jobs/create-job.html', context=context)
return render(request, 'auth/jobs/create-job.html', context=context)
def confirm_order(request, context):
print context
cleaned_data_job_creation_form = context['cleaned_data_job_creation_form']
cleaned_data_language_level_formset = context['cleaned_data_language_level_formset']
print request.POST['review']
if request.method == 'POST' and request.POST['review'] == True:
file = cleaned_data_job_creation_form['file']
count = 5 #simplified multiple rows
jobs = []
for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
language = language_level_form['language']
level = language_level_form['level']
d = {}
d['language_from'] = cleaned_data_job_creation_form['language_from'].name
d['language_to'] = language
d['number_of_characters'] = count
d['price_per_sign'] = 1
d['estimated_price'] = count * d['price_per_sign']
jobs.append(d)
table = CreatedOrdersTable(jobs)
context = {'table': table,
'cleaned_data_job_creation_form': cleaned_data_job_creation_form,
'cleaned_data_language_level_formset': cleaned_data_language_level_formset}
return render(request, 'auth/jobs/confirm-order.html', context=context)
else:
for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
language = language_level_form['language']
level = language_level_form['level']
Job.objects.create(
customer=request.user,
text_to_translate=cleaned_data_job_creation_form['text_to_translate'],
file=cleaned_data_job_creation_form['file'],
short_description=cleaned_data_job_creation_form['short_description'],
notes=cleaned_data_job_creation_form['notes'],
language_from=cleaned_data_job_creation_form['language_from'],
language_to=language,
level=level,
)
return HttpResponseRedirect('/order-success')
You are returning a template render on your first view. So, the request doesn't end on your confirm_order view.
If you want, you can redirect to reverse('confirm_order') and add the data on session.
In your confirm_order view you will pop the data from session and continue with your flow.