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={})
Related
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()
I have a list of items in a view called client_items. I want to be able to use the variable items_list`which is another view called edit_order in client_items. So is there a way to call the variable from a different view? (Import a variable from another view and be able to use this variable in the other) I cannot just write it in client_items view because it needs an order_no augment.
Edit: here is my latest views. I have tried creating another views called items_in_edit_order. At this point I get `order_no not defined.
def items_in_edit_order(order_no):
order = models.Order.objects.get(pk = order_no)
return order
def client_items(request, client_id = 0):
client = models.Client.objects.get(pk = client_id)
items = client.storageitem_set.all()
order = items_in_edit_order(order_no)
return render_to_response('items.html', {'items':items, 'client':client, 'order':order}, context_instance = RequestContext(request))
Just adding, since no one has said this and it seems like you don't understand this yet:
Your client_items view must, somehow, have access to the order_no variable. If for some reason the value is not being passed along via the URL, it must get the value from somehwere. There are only three real locations where it could get this value:
Database: this will work if you are, for example, storing something like a cart which is directly linked to a user. So for example, you might be able to do something like order_no = Order.objects.filter(cart__user=request.user).order_no which would get the order associated with the user's current cart, then return the order_no value.
Session: you store the order_no in the session. This would assume you had an earlier view where the value for order_no was set, at which point you would save it using request.session['order_no']=order_no. Later, when you wanted to retrieve the value, you would simply use order_no=request.session['order_no'] in the view.
Cookie: not really recommended, but an option nonetheless. It's complicated because in the first view you'd have to create the response object (as in resp = render_to_response(template_name, locals(), RequestContext(request)) and then write a cookie to it resp.set_cookie("order_no", order_no). You retrieve it using request.COOKIES['order_no']
There are other, bizarre, places you could store the value: files, cache, other data storage formats, etc. Not at all recommended.
No. Write a function that returns the value you're interested in, and call it from both views.
What the guy said above is correct. You shouldn't attempt to "share" variables to different views.
However in the event you must or have a reason to then you could just store it in the session and then you have access to it in any view that has access to the "request".
Hope that helps.
How can I redirect from view to another url, passing my queryset to another view?
I tried this:
return simple.redirect_to(request, 'some_url', **{'queryset': results})
and this
return redirect('some_url', queryset=results )
but it does not work....
How can i do it?
Gabi.
How are you expecting this to work? Redirection happens by getting the browser to request another URL. Anything you want to pass as a parameter to the redirection must therefore go into the URL you're redirecting to. It simply doesn't make sense to put a queryset into a URL parameter.
Presumably you could pass whatever arguments you used to get the queryset in the first place, but that's a lot of extra work.
Do you really need to redirect at all? What about simply calling the new view from your original one, and returning its response?
I'm trying to call a view directly from another (if this is at all possible). I have a view:
def product_add(request, order_id=None):
# Works. Handles a normal POST check and form submission and redirects
# to another page if the form is properly validated.
Then I have a 2nd view, that queries the DB for the product data and should call the first one.
def product_copy_from_history(request, order_id=None, product_id=None):
product = Product.objects.get(owner=request.user, pk=product_id)
# I need to somehow setup a form with the product data so that the first
# view thinks it gets a post request.
2nd_response = product_add(request, order_id)
return 2nd_response
Since the second one needs to add the product as the first view does it I was wondering if I could just call the first view from the second one.
What I'm aiming for is just passing through the request object to the second view and return the obtained response object in turn back to the client.
Any help greatly appreciated, critism as well if this is a bad way to do it. But then some pointers .. to avoid DRY-ing.
Thanx!
Gerard.
My god, what was I thinking. This would be the cleanest solution ofcourse:
def product_add_from_history(request, order_id=None, product_id=None):
""" Add existing product to current order
"""
order = get_object_or_404(Order, pk=order_id, owner=request.user)
product = Product.objects.get(owner=request.user, pk=product_id)
newproduct = Product(
owner=request.user,
order = order,
name = product.name,
amount = product.amount,
unit_price = product.unit_price,
)
newproduct.save()
return HttpResponseRedirect(reverse('order-detail', args=[order_id]) )
A view is a regular python method, you can of course call one from another giving you pass proper arguments and handle the result correctly (like 404...). Now if it is a good practice I don't know. I would myself to an utiliy method and call it from both views.
If you are fine with the overhead of calling your API through HTTP you can use urllib to post a request to your product_add request handler.
As far as I know this could add some troubles if you develop with the dev server that comes with django, as it only handles one request at a time and will block indefinitely (see trac, google groups).
I have written a function having the following signature:
def action_handler(request, model):
This action_handler is used from different views and handles the actions for this views. One example is deleting objects. In this example the user selectes some objects, selects the delete action and then the user is presented a page to check whether he/she wants to really delete the selected objects. This is done by the following code:
context = {
'action_name' : selected_action,
'object_list' : object_list,
}
return render_to_response("crm/object_delete_check.html", context,
context_instance=RequestContext(request))
For the case that something goes wrong I want to redirect the user to the view from where the user called the action.
Thus I want to ask here whether it is possible to get the calling view from the request object or somewhere else from.
If the def "def action_handler(request, model):" is called from the view "contacts(request):" then i want to redirect the user to the view "contacts(request):" .
But the clue is I do not want to hard-code it since the def action_handler is called from different views. Using a simple "return" is also not possible, since I want to recall the view completely.
if goback: #goback being whatever criteria means "something went wrong"
default_back_url = "someurl_in_case_the_meta_is_messed_up"
back = request.META.get('HTTP_REFERER',default_back_url) #yeah they spelled referrer wrong
if back:
return HttpResponseRedirect(back)
else:
return HttpResponseRedirect(default_back_url)
while META can be faked, it's harder to fake than GET query strings.
You can pass previous page url through GET parameter:
/object_delete_check/?previous=/contacts/
(see contrib.auth.decorators.login_required for example)