Django redirect not working? - django

If a user wants to delete the post I want to return them back to their accounts page, however, with the code below it returns them back to the edit page where they can edith their posts. It doesn't delete the post?
def airline_delete(request, id=None):
instance = get_object_or_404(Airline, id=id)
instance.delete()
return redirect('upload_overview')
url
#account/upload/edit/ (Edit airline)
url(r'^account/airlines/edit/(?P<id>[0-9]+)$', airline_update, name='airline_update'),
#account/upload/delete/(Delete airline)
url(r'^account/airlines/edit/(?P<id>[0-9]+)$', airline_delete, name='airline_delete'),
How do I fix that?

Your URLs are the same, so only airline_update will ever be called. You should probably make the delete URL contain "delete" instead of "edit".

If you want to use same url you could use class based view with put (for edit) and delete (for delete) methods which would use same url pattern. But in that case you should also call with appropriate HTTP methods PUT for put method and DELETE for delete method.

Related

Choosing correct Django delete view approach

I'm working on Django website and I have problem in figuring out correct/good way to handle delete view. From what I found out there are two ways to approach it:
1
class ObjectDeleteView(DeleteView):
model = Object
def get_success_url(self):
objectid = self.kwargs['object_id']
object = Object.objects.get(id = objectid)
container = object.container
containerid = container.id
url = reverse('Containers:showContainerContent', args=[containerid])
return url
def get_object(self):
return get_object_or_404(Object, pk=self.kwargs['object_id'])
2
def objectDelete(request, object_id):
object = Object.objects.get(id = object_id)
container = object.container
containerid = container.id
url = reverse('Containers:showContainerContent', args=[containerid])
return HttpResponseRedirect(url)
From what I can tell both are doing exactly the same thing - once object is deleted present user with page under Containers:showContainerContent.
The big difference I am experiencing is error I am getting when running unit test for this (simple call of the website and check of response code). With option 1 I end up getting error
django.template.exceptions.TemplateDoesNotExist: ContainerApp/object_confirm_delete.html
Which I understand - I don't have this template, this is default template for DeleteView, hence error is correct. The thing is I don't want to have any extra page. Just redirect user and that's it.
Also, I tested changing return url to return HttpResponseRedirect(url) in option 1, but result is the same.
What should I do here? Should I just continue with option 2? What are or might be the drawbacks for this approach?
There is a major difference between two class based delete view and function based view (the way you declared it).
CBV accepts get, post and delete http methods. When you send a get request to class based view, it does not delete the object. Instead it renders template with object to be deleted in context. This is basically used to have confirmation. For example you can send a get request and it will render a template with text "Do you really want to delete?" or "Please confirm blah blah..". And if you send a post or delete request, it will actually delete the object and redirect to next page.
FBV, on the other hand, give you full control over what you want to do. And as you declared it, it will accept any request type and delete the object and redirect to next page because you have not done any request type check in your view which is not a great idea IMHO. You should not allow deletion on get requests. They should be idempotent. There are plenty of otherthings that CBV provides. For example in case the object does not exist your FBV will crash. CBV, on contrary, will return proper 404 response if object does not exist.
So I think there is no bad in using FBV, but make is strong and secure enough that it handles every case (what if object does not exist?, what about confirmation?, GET should be idempotent only allow deletion with post? etc etc). Or simply use CBV.

Django Processing Form to other Form

I have a view that is an input form that people input their information in (name, address, that sort of thing). They will then click an "ok" button.
After people click "ok" I want them to be redirected to a page that has a table with their inputted information.
Any ideas on how to do this?
So far, I have the first view. When clicking OK all the information is stored in a database. I just don't know how to use it from there.
Note: ModelForms are used
If you look carefully the documentation : https://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form
You could understand that, once you have treated (is_valid() - cleaned_data['']), you have to do a call to
render_to_response('template',{ 'name':name, 'last_name':last_name..}, context_instance=RequestContext(request))
And, in the template called, just make the data you need be shown, as usual..
you could try to pass your newly created object to the next view (which shows the new object) like this, the called view just has to accept your object as parameter.
# ... your form processing here
if form.is_valid():
# create and save your object code here
your_object.save()
return redirect('show_new_data_view', your_object=your_object)
Hope this helps.

Django, Pass QuerySet to url using redirect/redirect_to

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?

Django: Passing a request directly (inline) to a second view

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).

django redirect to calling view after processing function

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)