beginner django: next button acts as Submit - python

Disclaimer: I am new to python and django but have programmed in Drupal
I am developing a web-based Wizard (like on Microsoft Windows installation screens) with explanatory text followed by Previous and Next buttons (which are big green left and right arrows). So far, so good.
However, my current Wizard page (in project.html, loaded by my django apps views.py) now uses a form (instance of ModelForm) which asks the user to type in a "project" name, such as My Project. Normally, such an HTML form would use a Submit button, but because this is a Wizard, I need the Next button to act as the Submit button, hiding the Submit button entirely. Also, the arrow icons appear after the form ends.
How would you do this? Sure, I could use jquery, but is there a better pythonic or django way?
Some code:
#project.html
{% extends "base.html" %}
{% load i18n %}
<h3><span>{% trans 'Project details' %}</span></h3>
<p>{% trans 'What is the name of this project?' %}
<form method="post" action="">
{{ form.as_table }}
<input type="submit" value="Submit"/>
</form>
</p>
{% endblock %}
{% block buttonbar %}
<img src="/static/img/Button-Previous-icon-50.png" width="50" height="50" alt="Previous"><span>{% trans 'Previous' %}</span>
<img src="/static/img/Button-Next-icon-50.png" width="50" height="50" alt="Next button"><span>{% trans 'Next' %}</span>
{% endblock %}
Thanks!

<input type="submit" value="Next"/>
This gives you a button with the value 'Next' which acts as a submit button. If this is not what you've wanted, rephrase your question and/or give an example of what action should take place after pressing next.

You might want to use the Django Form wizard, in this case:
https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/

Related

Failed to get value from html page in Django

I have a problem with trying to get a response from my HTML page using Django (admin).
I have a pretty simple div = contenteditable and need to pass data from this div back after the submit button was clicked.
Everything, including choosing selection and opening the intermediate page works fine. But when I tapped submit button, the condition if "apply" in request.POST failed to work.
Please, tell me, what I'm doing wrong?
This is my Django admin:
class QuestionAdmin(AnnotatesDisplayAdminMixin, admin.ModelAdmin):
def matched_skills(self, question):
return ', '.join(s.name for s in question.skills.all())
def update_skills(self, request, queryset):
if 'apply' in request.POST:
print("something")
skills = []
for question in queryset:
skills.append(self.matched_skills(question))
return render(request,
'admin/order_intermediate.html',
context={'skills': skills})
update_skills.short_description = "Update skills"
This is my order_intermediate.html page:
{% extends "admin/base_site.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<h1>Adjust skills. </h1>
{% for skill in skills %}
<div>
<div id="title" style="margin-left: 5px" contenteditable="true" > {{ skill }} </div>
</div>
{% endfor %}
<input type="hidden" name="action" value="update_status" />
<input type="submit" name="apply" value="Update skills"/>
</form>
{% endblock %}
Actually, request.POST is an HttpRequest object. For getting available keys in the body of the request, you need to use "request.POST.keys()" method. So, you can simply change your condition to:
if 'apply' in request.POST.keys():
print("something")
In my knowledge, you can not send div content with form submit. However you can use input tag with array in name attribute for this. This will send an array as post variable when submit
First, send skills as a enumerate object from your views
return render(request, 'admin/order_intermediate.html', context={'skills': enumerate(skills)})
Then edit your html to this (Note: if you have css in title id, change it to title class)
{% for i,skill in skills %}
<div>
<input class="title" name="skill[{{ i }}]" value="{{ skill }}" style="margin-left: 5px">
</div>
{% endfor %}
and handle array with any action you want to perform in update_skills()
for skill in request.POST.getlist('skill[]'):
# your code

Django - Conditional Rendering In Templates

I need some help conditionally rendering data in a modal pop up window on my site.
What I want to do:
When the user clicks on the "make reservation" button, I want to display this in the modal window
<h3 style="margin-top:20px;">Choose dates</h3>
<div style="margin-top:20px;" class="pick-dates-div">
<form method="GET" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="form-btn save btn btn-default">Make A Reservation</button>
</form>
<button style="margin-top: 25px;" class="btn-primary btn-block btn-lg" data-toggle="modal"
data-target="#inquiryModal">More
Questions ?</button>
</div>
Then the user can pick the dates from the date picker and press the "make a reservation" button ( which is a GET request ), the page refreshes and I want to display only this in the same modal window :
<h1>Start Date: {{ date_start }}</h1>
<h1>End Date: {{ date_end }}</h1>
<h1>Price Per Day: ${{ price_per_day }}$</h1>
<h1>Total: ${{ total_price }}$</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button href="www.facebook.com" type="submit" class="form-btn save btn btn-default">Confirm Reservation</button>
</form>
After that the user submits the form ( POST request ) and I want to display a text :
<h3> Thank you for your reservation </3>
What would be the ideal way to achieve this ?
Thank you stack
The ideal way to achieve this is by using JavaScript.
One of the many methods this could be achieved is by rendering all the three views inside separate containers in a modal and then hiding the next two using javascript.
You can use element.style.display = 'none' to hide and
element.style.display = 'block' to show the content inside the element container.
Once the user clicks on "make reservation" button, hide/show the required containers to achieve the desired result.
Do not forget to secure your website by using proper validation on the server end. Hope that helps!

Django: urls in html form not working correctly

I am building e-commerce website, I have a shopping cart model with items, I want the customer to select the quantity of a certain item they want to buy, this is the reason I am placing everything in a form to later grab the quantity in views.py by request.POST.getlist('quantity') and pass the data to 'Sales:checkout'. But in there I also have button to delete an individual item form the shopping cart (Sales:delete_cart_item) and a button for emptying the whole cart (Sales:empty_cart).
Now to the problem, when I press any of the latter buttons, be it Sales:delete_cart_item or Sales:empty_cart they all execute Sales:checkout, please help me figure out what I'm doing wrong
from shopping_cart.html:
<form action="{% url 'Sales:checkout' %}" method="POST">
{% csrf_token %}
{% for item in items %}
<td>{{ item.item.item_name }}</td>
<td>
<input type="number" name="quantity" min="1" max="{{ item.item.stock_level }}">
</td>
<td>{{ item.item.id }}</td>
<td>
<button>Delete row</button>
</td>
{% endfor %}
<form action="Sales:empty_cart" method="POST">
<button type="submit">Empty Cart</button>
</form>
<button type="submit">Continue to Secure Checkout</button>
</form>
please ask if you need additional details, I'm open to any way of solving this problem even if it requires to maybe rewrite a view, I don't necessarily want to place everything in a form, this is just the closest I got to doing it
This is because both your buttons trigger a submit of the checkout form when they are clicked.
You shouldn't put a form within another, as any submit button, even in the "inner" form, results in the "outer" form being submitted.
So I suggest you move both the "delete item" (along with its wrapping link) and the "empty cart" buttons (along with the latter's form) outside of your checkout form.

How does the {{ form }} tag work in Django-registration app

I downloaded and installed django-registration app. I also downloaded a template that has this strange piece of code
{{ form }}
that magically creates 4 labels and 4 textboxes for the user to enter his registration information. How does it work?
{% extends "registration/registration_base.html" %}
{% block title %}Register for an account{% endblock %}
{% block content %}
<table>
<form method='post' action=''>{% csrf_token %}
{{ form }}
<tr><td></td><td><input type="submit" value="Send activation email" /></td>
</form>
</table>
{% endblock %}
It is part of django forms. See the documentation for more info.
https://docs.djangoproject.com/en/1.3/topics/forms/
If you are really interested check out the source code.
https://code.djangoproject.com/browser/django/trunk/django/forms
A django form (but other objects, too) has a unicode method, which is invoked, when a string representation of the object is requested. As you can see in the code, it just passes the call on to as_table - which in turn uses a generic helper function: _html_output. This basically loops over all the fields and constructs the HTML which then is returned and displayed on the page.

How to realize a dynamic sidebar with Django?

I plan on creating a sidebar with changing elements (depending on the current url and authentication-status).
For example: The default sidebar shows a login and a tag cloud.
If a user is already logged in, I want to display a user menu.
If the current url is /tagcloud, I want to hide it from the sidebar.
Actually, I need a way which enables me to do something like this in a view:
def some_view(request):
if request.user.is_authenticated():
sidebar.remove('login')
sidebar.add('user_menu')
def tag_cloud(request):
sidebar.remove('tag_cloud')
Afterwards, I want to pass the sidebar (implicitly, without passing it to render_to_response) to the template where I have in mind to do something like this:
<div id="sidebar">
{{ sidebar }}
</div>
Is this possible?
You'd better do this in a context_processors.py file
That also mean you have to use a RequestContext when returning your views
def include_tagcloud(request):
if request.path == '/tagcould/':
tagcloud = Tags.objects.filter(active=True) #whatever
return {'tagcloud': tagcloud}
def include_login(request):
if request.user.is_authenticated():
loginform = MyLoginForm(request.POST)
#passing a Django form + POST data in the case of re-submit
return {'loginform' : loginform}
And then in your template :
{% if loginform %}
<form action="accounts/login/">
{{form.as_p}}
<input type="submit" name="Login">
</form>
{% endif %}
{% if tagcloud %}
{%for tag in tagcloud %}.....{%for}
{% endif %}
In this example the login form points to a fixed view,
if you want to catch the login form post on everyview, I don't know how to do
EDIT : if you don't use the CSRF features of Django, you could simply insert the login form in the base template without using any django form and pointing to a login view :
{% if user.is_authenticated %}
<form action="accounts/login/">
<input type="text" name="username"><input type="password" name="password">
<input type="submit" name="Login">
</form>
{% endif %}
Yeah, but you can use inheritance of templates as well as composition. Then include your sidebar in a parent template that is used/inherited from in all of your templates. Then it is easy to find the template for the sidebar: it's in a separate file.
Answer of #Dominique is correct but When you write something in context_processors that's load at any page of the website. That maybe makes a performance issue.
I think the right way to handle dynamic sidebar is simpletag and use where you need.
def get_sidebar():
tags = Tags.objects.filter(active=True)
latest_posts = Post.objects.all().order_by('-create_at')[:10]
html = render_to_string("sidebar.html", {
"tags": tags,
"latest_posts": latest_posts
})
return html
And now just use in template files:
<div class="col-md-4 sidebar">
{% get_sidebar %}
</div>
Also, you can pass request to simpletag to use user.is_authenticated for authenticated user access.

Categories

Resources