I am using Boostrap modal fade window which renders Django form to update my database records. And what I fail to do is not to reload the page if the user has opened the Update window and did not change anything. It will be easier to get my idea if you look at the code below:
def updateTask(request, task_id):
#cur_usr_sale_point = PersonUnique.objects.filter(employees__employeeuser__auth_user = request.user.id).values_list('agreementemployees__agreement_unique__sale_point_id',flat=True)
selected_task = Tasks.objects.get(id=task_id)
task_form = TaskForm(instance=selected_task )
taskTable = Tasks.objects.all()
if request.method == 'POST':
task_form = TaskForm(request.POST,instance=selected_task)
if task_form.has_changed():
if task_form.is_valid():
# inside your model instance add each field with the wanted value for it
task_form.save();
return HttpResponseRedirect('/task_list/')
else: # The user did not change any data but I still tell Django to
#reload my page, thus wasting my time.
return HttpResponseRedirect('/task_list/')
return render_to_response('task_management/task_list.html',{'createTask_form':task_form, 'task_id': task_id, 'taskTable': taskTable},context_instance=RequestContext(request))
The question is, is there any way to tell Django to change the url (like it happens after redirecting) but not to load the same page with same data for the second time?
It's not trivial, but the basic steps you need are:
Write some javascript to usurp the form submit button click
Call your ajax function which sends data to "checking" view
Write a "checking" view that will check if form data has changed
If data have changed, submit the form
If not, just stay on page
This blog post is a nice walkthrough of the entire process (though targeted towards a different end result, you'll need to modify the view).
And here are some SO answers that will help with the steps above:
Basically:
$('#your-form-id').on('submit', function(event){
event.preventDefault();
your_ajax_function();
});
Call ajax function on form submit
Gotta do yourself!
Submit form after checking
Related
I have a Django form that takes filter options for a report. The report page is a separate view that renders the report based on the form data.
My first pass at this, I simply set the action of the form to the report page and method to GET. The form data was then passed directly the report view via the querystring which I would use GET to retrieve. The problem with this was that this bypassed form validation since the the form did not post back to its own view.
My next pass, I removed the form action (so it would post back to itself) and used form_valid (I am using class based views) to encode the form data and redirect to the report view like so:
ReportOptionsView(FormView)
form_class = OptionsForm
template_name = 'my_report_options.html'
report = reverse_lazy('my_report')
def form_valid(self, form):
qstr = urlencode(form.cleaned_data)
return redirect(self.report+"?"+qstr)
The report page works the same -I just retrieve the information from the querystring to filter the models and display the report.
I would prefer the form data not appear on the querystring of the report page. When I tried to redirect to the report page using a POST method is where I starting having trouble. Even going back to my original flow setting the form action to the report page (thus losing validation) and setting the form method to POST, I got 405 errors. I realize that there may be ways to do this using Javascript, but would prefer to stick with Django/Python
My question is, what is the proper method in Django to take cleaned data from a validated form and POST that data to separate view so that the form data is not exposed in the URL?
I am struggling with the update of database information with the forms, and simply passing information between views. I could really use some advice because I am fairly new to Django.
The flow goes like this:
1. First form; I transfer the article price and title to the view "event"
2. The view "event" handles title and price and ask for confirmation in the html form
3. Once confirmed, it directs that information to the view "transact_test", I want this view to handle the update of the database via a new form that is build with the Article model. But it provides the error message : "didn't return an HttpResponse object. It returned None instead."
To fix your error: In transact_test you are just calling render in the request.method == 'POST' block:
render(request, ...)
You need to return render:
return render(request, ...)
You should really take a look at some additional django tutorials you are making this harder than you need to. You should almost never manually render a form when using django. And as Tariq said, please don't use images.
I am working on my first Django site. I setup an html page that accepts user inputs, runs calculations, saves to the database, and displays output values into a form when the user hits a submit button. Now I would like to add functionality for a dropdown to call up one of those submissions from the database if a user selects a item from the dropdown. So, I created a second form on the same html page for the drop down and successfully populated the dropdown list, however, can't figure out how to load data to the original form when the dropdown is selected. I think this can be accomplished with form attributes, but I am not sure.
Example:
if request.method == 'POST' and form.is_valid():
This posts the users inputs to the db and displays the calculation
elif request.method == 'GET' and 'dropdown' in request.POST:
Here lies the problem. When I select an item in the dropdown nothing
happens, or I get an error on the page load. I have tried lots of
different approaches the above is the latest.
else:
A bunch of variables = None
Can anyone provide some coaching or an example?
So I have a a HTML page with a table in it which contains details of a certain model. Each row contains details of a different object. I have a cell for a button as well.
Now, what I want is for the user to be able to click on the button and it should take them to the appropriate page for that particular user that they've clicked on. The way I can do this now is by creating a URL that takes a user_id argument along with a view to redirect it to a template. This url can then be added to the button. However, I don't want the user_id to be shown in the URL (being shown in Inspect Element is okay (as in the row ID)).
This rushed, so sorry. How can I do this?
Is there a way to do it without putting any information whatsoever in the URL?
Thank you!
One way to do this is to send user ids from a POST instead of a GET for getting the user info, when the user clicks the button, you submit a hidden form which contains user_id (which you will update accordingly) and pass it to Django. On this POST call you will wire a render of the page for the user according to the POST parameter you are expecting containing the user id.
You can read the post parameters on a request via:
request.POST.get('user_id')
The downside of this approach is that you won't be able to share the link for a certain user, because the link will only contain the get parameters.
Maybe you can refactor your application to use some kind of SPA framework on the front-end. In this way you can load any content on your current page and the URL never changes if you don't want. Take a look for example at AngularJS or Durandal. Both works well with Django.
You can also solve the problem by using POST instead of GET but in my opinion that's not a very elegant solution because POST requests should be used just when you send data to the server.
If your worried about security I don't think keeping the user_id secret will be effective but if for some other reason you have to do this put it in session and redirect to user page without any parameters.
Put your table inside a form and store the id in an attribute of the button on each row:
<button class="mybutton" data-id="{{ my_object.id }}">view</button>
Put a hidden field at the bottom of your form:
<input type="hidden" id="user_id" name="user_id" />
Javascript:
$("table .mybutton").click(function(e) {
e.preventDefault();
$("#user_id").val($(this).attr("data-id"));
$("#my_form").submit();
});
In your table view:
if request.method == "POST":
request.session["user_id"] = request.POST.get('user_id')
return redirect("user_page")
In your details view:
user_id = request.session["user_id"]
creating urls
If the url is relevant to the user; then use the user_id; e.g. http://example.com/mysite/users/<user_id>/userstuff.
obfuscation is not security.
obfuscation is not a permission scheme.
Other possibilities:
http://example.com/mysite/users/<uniqueusername>/userstuff.
http://example.com/mysite/users/<slug>/userstuff.
http://example.com/mysite/users/<encoded>/userstuff, where encoded is either 2-way encoding, or a field on the user model that is unique.
getting logged in user (request.user)
If the url has nothing to do with the user, but you need to get the authenticated user then read the docs: https://docs.djangoproject.com/en/1.7/topics/auth/default/#authentication-in-web-requests.
def my_view(request):
if request.user.is_authenticated():
# use request.user
else:
# something else
I have a view (views.loaditems) which runs some algorithm and passes items to a template(product.html) where the items are loaded, and with each item, I have a "add_to_shortlist" link. On clicking this link, the item is added in the user's shortlist (for which I have a function). I want that on click, the page is not reloaded and has its items, but simply add that item to the user's shortlist. Also, where should I define this shortlist function?
I'm new to Django, and any help would be much appreciated. Thanks.
Update: Here's my code:
views.py
def loaditems(request):
#some code
ourdeals = SDeals.objects.filter(**{agestring3:0})
sorteddeals = ourdeals.order_by('-total_score')
user = request.user
context = {'deals': sorteddeals, 'sl_products':sl_products, 'user':user,}
template='index.html'
return render_to_response(template, context, context_instance=RequestContext(request))
def usersl(request, id, id2):
userslt = User_Shortlist.objects.filter(id__iexact=id)
products = SDeals.objects.filter(id__iexact=id2)
product = products[0]
if userslt:
userslt[0].sdeals.add(product)
sl = userslt[0].sdeals.all()
return render_to_response('slnew.html', {'sl':sl}, context_instance=RequestContext(request))
in my index.html I have:
<div class="slist"></div>
which in urls.py takes me to views.usersl:
url(r'^usersl/(?P<id>\d+)/(?P<id2>\d+)/$', views.usersl),
I don't want to go to slnew.html, instead be on index.html without reloading it, and on click 'slist', just run the function to add to shortlist.
In order to make changes on the server and in a page without navigating with the browser you need to look at JavaScript solutions. Read up about Ajax. In essence you need to use some JavaScript to send the update to the server, and to change the HTML.
JQuery is one popular library that will help you to do this. A more sophisticated example is AngularJS. On the Django side you'll write some views that handle these small update tasks used in the page. Libraries like Django REST framework or Django Slumber will help you with that.