Django - how to pass more than one primary key to the view - django

I need to write a view to delete multiple objects in one go.
I have modified the HTML template, put checkboxes to select which objects (users) to delete and a button to delete them, but of course you need a view to perform the task.
When you have one item to select at a time, you pass its primary key to the view through the url, how can I extend this to pass more than one primary key?

You would absolutely not be doing this via the URL. If you have a set of checkboxes, then you have a form; since the form is doing destructive operations it will be submitted via POST: therefore your set of IDs is in request.POST.

What you can do is to send the data in a JSON format, which can easily be decoded by Django
On the frontend, you'd have a JavaScript for a button like so,
function delete_object(pks) {
var args = {type: "POST", url: "/delete/", data: {'pks': pks}};
$.ajax(args);
return false;
}
this function would take selected the primary keys from (which is passed in as pks) and POST it to the Django url ^delete/$. A Django view function can then handle the incoming data like so,
def delete(request):
object_pks = request.POST['pks']
Docs.objects.filter(pk__in=object_pks).delete()

Related

Passing GET params to a Django View internally

I am trying to call a Django view internally from another view:
response = BlogViewSet.as_view({'get':'list'})(request)
BlogViewSet is actually a rest framework view.
The above code works and I can access response.data but what I actually want to do is pass in some GET params to do some filtering. I tried the following but it didn't work:
response = BlogViewSet.as_view({'get':'list'})(request, my_param=something)
I realise I could modify request to add GET params but it seems wrong to modify it as it might be used later in the view.
You shouldn't ever call the view itself form another view.
You should instead try to extract the meaningful data / code out of the BlogViewSet view and call them directly from the various views.
Calling one view from another is a bad practice.
Why not request url of the view instead of calling the view itself.
r = requests.get("<url_to_access_view>", params={})

Django - Create new object in Form, update select box and save it

I think what I'm trying to achieve is not hard, but I have no clue how to do it hehehehe !
Basically what I need is the feature that we have in Django Admin, when you are creating a new object, if you have a Foreign Key, you can add new data (opening a pop-up), save it and then the select box updates automatically.
What I have is this form:
I know that would be easy to do it with some Javascript, but my point is, Django has some rules, and as far I know, I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
PS: "Local" is the select box where I want to add new data. The user should be able to create a new Local on this page, instead of going to another page to do it. Thanks :)
Here your question:
I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
Then the answer:
you are right, django will check values match form value rules. But:
realize that your main form is invoked for twice: on GET and on POST. Between both form executions you make changes on database values trhough your new form. That means that in second main form invocation the value added to database is available:
field1 = forms.ModelChoiceField(queryset= ***1*** )
***1***: on second invocation new value is already available on field1.
Then, you don't should to be afraid about this subject, the new value will be available on form on your main form POST request.
Nothing wrong with updating the value using javascript as long the key in your new combo box has the right key in the database then it should be ok.
Call this function after you saved the last entry.
function refreshLocal(){
$.get(window.location.href, '', function(html){
// change the id to the local combox's id
var serverLocalDropBox = $(html).find('#id_local');
if (serverLocalDropBox.length){
$('#id_local').replaceWith(serverLocalDropBox);
}
})
}
If you don't want to use javascript solution, you can post the form with refresh flag and on the server side if you see that flag just don't validate and return the form as is. Since you have a new entry in the foreignkey it will automatically update the queryset to include the new entry.
function serverRefreshLocal(){
var $form = $('#your_form_id');
$form.append('<input type="hidden" name="refresh" value="true" />');
// you can use ajax submit and ajax refresh here if you don't want to leave the page
$form.submit();
}
// Server Side
def your_form_post_view(request):
if request.POST.get('refresh', 'false') == 'true':
# initial is the trick to save user input
your_form = YourForm(initial=request.POST)
context = {
'form': your_form,
}
return render(request, 'your_template.html', context)
# your view code goes here

how to pass a template's data to another template using iron router (not on query parameter)

I m new to iron router and want to pass one template'data to the calling template through Router.go() method. But i found it can be pass through query but i don't want to use query as my data is large JSON object.
So, is there a way to pass data from one template to another template using iron-router.
any help would be highly appreciated.
Save it to some local collection then use the ID in the url is one way.
JSONCollection = new Mongo.Collection('some_json');
Template.yourTemplate.events({
'click button[data-action="go-to-next"]': function (e, template) {
var id = JSONCollection.insert(template.data);
Router.go('yourroute', { _id: id });
}
});
Then your url will just contain the id.
/yourroute/:someIdHere
Use Session.set() before calling Router.go() and Session.get() on another template. This approach doesn't require round trip to database but be sure to not flooding Session object as it will persist throughout browser session.

Can i hide the query params from the URL?

In my Ember.js Application, I am dealing with query params for list updates. I have one strange use case, in which I don’t the URL to be updated with certain query params. How can I achieve this?
I assume you want to reload your model with parameters that are different than the ones in your application route? And you keep your application route parameters synced using queryParams?
In your route's model function you can filter your model data by the same query params (that appear in the address bar) but you can add some logic that extracts additional parameters either from the controller or other place and these parameters the data fetching query. Example:
model: function(queryParams) {
var params = queryParams;
params.additional_filter = this.controllerFor('mycontroller').get('additional_filter');
return this.store.find('mymodel', params);
}
Also if you want to explicitly reload the model you will need to call Router.refresh() function.

Wizard input - DB View - Dynamic where clause

I was trying to pass where condition values onto a database view.
View was created in init method of class defined.
Input to where clause was taken from a popped up wizard.
Issue is that the wizard form values are inserted into model bound database table.
This is happening on all submits.
Currently I am reading the latest record from table on wizard input.
And the view definition is modified to generate result set based on latest input record from wizard table.
select v.col1, v.expre2
from view_name v,
( select fld1, fld2 from wizrd_tbl_1 order by id desc limit 1 ) as w
where
v.colM between w.fld1 and w.fld2
Currently I am following the above sequence of steps and results are fetched.
But I think, this would fail if at least two users are using the same wizard concurrently.
How can I change my approach, so that
1. Wizard input is not sent to database table,
2. The inputs are sent to a where clause dynamically and the result set is bound to a List View
As a summary, I was trying to:
Creates a database view joining multiple table.
Take user input ( and saves in db table, which is not expected and
not required ).
Pass the user input to db view's where clause. ( Any alternative to wizard ? )
Bind the result set to List View
It is definitely a bad idea to morph a database view based on user input, when that view is likely to be accessed by multiple users.
The 'correct' way to do this would be to have a static database view which contains all possible records from the joined tables, and then filter that data for individual users by generating a "domain" and redirecting the user to a tree view with that domain applied.
You can redirect the user by creating a <button type="object"> which calls a function such as the below:
def action_get_results(self, cr, uid, ids, context={}):
# Redirect user to results
my_domain = ['&', ('col1','=','testval'), ('col2','>',33)]
return {
'type': 'ir.actions.act_window',
'name': 'Search Results',
'view_mode': 'tree',
'res_model': 'your.osv_memory.model.name',
'target': 'new', # or 'current'
'context': context,
'domain': my_domain,
}