I have two functions in views.py, the first one allows you to display information from tables. The second is to get data from the form and redirect to the page with the result. How can I pass the data received from the form to the first function to display information from the tables based on this very data?
In the first function:
def SuOp(request):
allrooms = Rooms.objects.all()
allfood = Food.objects.all()
alltours = Tours.objects.all()
data = {
'allfood': allfood,
'allrooms': allrooms,
'alltours': alltours,
}
return render(request, './obj.html', data)
in the second function:
def Main(request):
error = ''
if request.method == 'POST':
form = SearchMain(request.POST)
if form.is_valid():
budget = form.cleaned_data.get("budget")
arrival_date = form.cleaned_data.get("arrival_date")
departure_date = form.cleaned_data.get("departure_date")
number_of_people = form.cleaned_data.get("number_of_people")
count_days = (departure_date-arrival_date).days
return redirect('allobject')
else:
error = 'The form has been filled out incorrectly'
form SearchMain()
data = {
'formS': form,
'error': error,
}
return render(request, './main.html', data)
urls.py:
urlpatterns = [
path('', views.Main, name='main'),
path(r'allobject/$', views.SuOp, name='allobject')
]
You can use sessions to pass values from one view to another. First set the session:
if form.is_valid():
budget = form.cleaned_data.get("budget")
request.session['budget'] = budget
...
return redirect('allobject')
Then your other view can get the session variable:
def SuOp(request):
budget = request.session.get('budget')
...
allrooms = Rooms.objects.all()
allfood = Food.objects.all()
alltours = Tours.objects.all()
data = {
'allfood': allfood,
'allrooms': allrooms,
'alltours': alltours,
}
return render(request, './obj.html', data)
The other option is to do all the calculations in the view that receives the budget, arrival_date, departure_date, number_of_people, save the desired results to the Rooms, Food and Tours objects.
Related
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)
I am receiving the following error when submitting a form.
ValueError at /edit_entry/hi/
The view encyclopedia.views.edit_entry didn't return an HttpResponse object. It returned None instead.
Here is the views.py that is triggering the error.
def edit_entry(request, title):
if request.method == "POST":
form = NewEditEntryForm(request.POST)
if form.is_valid():
title = form.cleaned_data["title"]
content = form.cleaned_data["content"]
util.save_entry(title, content)
return HttpResponseRedirect("/wiki/" + title)
else:
form = NewEditEntryForm()
return render(request, "encyclopedia/edit_entry.html",{
"form": NewEditEntryForm(),
"title": title,
"content": util.get_entry(title)
})
What is the issue and how can I fix it?
(I also need help prepopulating the form with already existing data. I have tried using initial, but that has not worked. What is the best way to prepopulate the form with existing data?)
util.save_entry
def save_entry(title, content):
"""
Saves an encyclopedia entry, given its title and Markdown
content. If an existing entry with the same title already exists,
it is replaced.
"""
filename = f"entries/{title}.md"
if default_storage.exists(filename):
default_storage.delete(filename)
default_storage.save(filename, ContentFile(content))
sorry, I thought that you have a model.
# on util.py
def get_entry_content(title):
filename = f"entries/{title}.md"
return default_storage.open(filename).read()
# on views.py
def edit_entry(request, title):
if request.method == "POST":
form = NewEditEntryForm(request.POST)
if form.is_valid():
title = form.cleaned_data["title"]
content = form.cleaned_data["content"]
util.save_entry(title, content)
return HttpResponseRedirect("/wiki/" + instance.title)
else:
content = util.get_entry_content(title)
initial_dict = {
"title" : title,
"content" : content,
}
form = NewEditEntryForm(initial=initial_dict)
return render(request, "encyclopedia/edit_entry.html", {
"form": form,
})
All right, I think if this is not doing what you want, i would test the save_entry function in the console, creating and updating to see if it works or not.
I am trying to pass user data from one template inside of another template. For this I use an ajax request, as well explained here How do I integrate Ajax with Django applications?
although no error shows up, nothing gets pulled.
here is what my model formset view look like inside of template 1:
def New_Sales(request):
#context = {}
form = modelformset_factory(historical_recent_data, fields=('id','Id', 'Date','Quantity', 'NetAmount', 'customer_name'))
if request.method == 'GET':
formset = form(queryset= historical_recent_data.objects.none())
#blank_form = formset.empty_form
elif request.method == 'POST':
formset = form(request.POST)
#blank_form = formset.empty_form
if formset.is_valid():
request.session['sale'] = request.POST.get('sale')
for check_form in formset:
check_form.save()
quantity = check_form.cleaned_data.get('Quantity')
id = check_form.cleaned_data.get('Id')
update = replenishment.objects.filter(Id = id).update(StockOnHand = F('StockOnHand') - quantity)
update2 = Item2.objects.filter(reference = id).update(stock_reel = F('stock_reel') - quantity)
return redirect('/invoice/pdf/assembly/')
#else:
#form = form(queryset= historical_recent_data.objects.none())
return render(request, 'new_sale.html', {'formset':formset})
and here is the view to access template 1 data into template 2:
def generate_pdf_assembly(request):
my_company = MyCompany.objects.get(id = 1)
request = request.session.get('sale')
context = {'request' : request, 'my_company' : my_company }
print(context)
and here is the ajax request to access the data from the template (in template 2):
<h3> {{ context }} </h3>
<script>
$.ajax({
method: "GET",
url: "/new_sale.html",
sucess: function(context){
alert(context);
},
failure: function(context){
alert('got an error');
}
});
</script>
I feel like there must be an issue with the request.session in the view since no evident error gets outputed neither in log nor chrome console but I am not competent to debug it further at this point.
UPDATE: after changing context for request in tag template, the value None shows up, definitely an issue with the requesting
def username_exists(request):
data = {'msg':''}
if request.method == 'GET':
username = request.GET.get('username').lower()
exists = Usernames.objects.filter(name=username).exists()
if exists:
data['msg'] = username + ' already exists.'
else:
data['msg'] = username + ' does not exists.'`enter code here`
return JsonResponse(data)
I have a edit-scholarship.html in which you can search for a scholarship by passing name and type and then select that scholarship and edit it in update-scholarship.html by passing scholarship id from the url.
Now after updating the scholarship, the url becomes
http://127.0.0.1:8000/admin/updatescholarship/50
50 is the scholarship id passed into the url
Now when I try to go to dashboard in my project, the url becomes
http://127.0.0.1:8000/admin/updatescholarship/dashboard
I dont't want the dashboard to get appended after the updatescholarship . The url should be
http://127.0.0.1:8000/admin/dashboard
Here's my edit-scholarship view
def admin_editscholarship(request):
if request.method == 'POST':
name = request.POST['sch_name']
type = request.POST['sch_type']
schdets = ScholarshipDetails.objects.filter(name = name,type = type)
if schdets is not None:
#if something exists in scholarship details, then print it
print('Scholarship found')
else:
schdets = None
return render(request,'admin-editscholarship.html',{'schdets':schdets})
Here's my update-scholarship view
def admin_updatescholarship(request,pk=None):
#can update the new data in the selectd scholarship
if pk:
sch = ScholarshipDetails.objects.get(pk = pk)
if request.method == 'POST':
form = EditScholarshipForm(request.POST,instance=sch)
if form.is_valid():
form.save()
print('\nform saved')
args = {'form' : form}
messages.success(request,'Successfully updated')
return render(request,'admin-editscholarship.html',args)
Here's my urls.py
path('admin/dashboard',views.admin_dash),
path('admin/addscholarship',views.admin_addscholarship),
path('admin/editscholarship',views.admin_editscholarship),
url(r'^admin/updatescholarship/(?P<pk>\d+)$',views.admin_updatescholarship,name =
'updatescholarship'),
path('admin/students',views.admin_students),
path('admin/requests',views.admin_requests)
you can redirect to other url using django redirect
from django.shortcuts import redirect
def fn_test(request):
task here
return redirect('path_to_redirect/')
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.