Django: row still displayed after being deleted - because of caching? - django

I've written a Django app that uses DataTables. The problem is when I delete a row from the table it's still displayed in the table when running against nginx/gunicorn. However, it works correctly when I'm running against the Django test server. So if I start a server with this command line:
python manage.py runserver 192.168.0.1:8000
everything works fine. That is, I delete the row, the table refreshes, and the deleted row is not displayed.
This is a summary of the HTTP calls:
// An initial GET command to populate the table
GET /myapp/get_list (returns a list to display)
// I now select a row and delete it which causes this POST to fire
POST /myapp/delete (deletes a row from the list)
// After the POST the code automatically follows up with a GET to refresh the table
GET /myapp/get_list (returns a list to display)
The problem is when I use nginx/gunicorn the second GET call returns the same list as the first GET including the row that I know has been deleted from the backend database.
I'm not sure it's a caching problem either because this is the response header I get from the first GET:
Date Fri, 23 Dec 2011 15:04:16 GMT
Last-Modified Fri, 23 Dec 2011 15:04:16 GMT
Server nginx/0.7.65
Vary Cookie
Content-Type application/javascript
Cache-Control max-age=0
Expires Fri, 23 Dec 2011 15:04:16 GMT

The problem can be solved also by sending an added parameter to the server so that the browser doesn't cache the call. With jQuery you can simply use:
$.ajaxSetup({ cache: false});
Otherwise you must creat manually the parameter. Usually you create a timestamp
var nocache = new Date().getTime();
//send nocache as a parameter so that the browser thinks it's a new call

You can use Django's add_never_cache_headers or never_cache decorator to tell the browser not to cache given request. Documentation is here. I thinks it's cleaner solution than forcing the cache off in the javascript.
from django.utils.cache import add_never_cache_headers
def your_view(request):
(...)
add_never_cache_headers(response)
return response
from django.views.decorators.cache import never_cache
#never_cache
def your_other_view(request):
(...)

try this
oTable.fnDeleteRow( anSelected, null, true );
and b.t.w what version of datatables do you use?

I fixed the problem by changing
GET /myapp/get_list
to
POST /myapp/get_list
After doing this, I no longer get a cached response.

Related

DRF additional action without suffix [duplicate]

I'm working with two dev servers on my local machine (node & django's).
I've added django-cors-headers to the project to allow all origins & methods (on dev) with the following settings :
CORS_ORIGIN_ALLOW_ALL = 'ALL'
CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
)
I'm getting 405 when attempting DELETE.
Looking at the response headers
HTTP/1.0 405 METHOD NOT ALLOWED
Date: Mon, 03 Nov 2014 10:04:43 GMT
Server: WSGIServer/0.1 Python/2.7.5
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Access-Control-Allow-Origin: *
Allow: GET, POST, HEAD, OPTIONS
Notice that DELETE & PATCH / PUT are not present in the allowed methods list.
Is there something missing from my configuration ?
The response looks very similar to that of the list view (/api/resource/) for a ViewSet. List views only support GET, to list all of the objects, and POST to create a new object.
DELETE requests are only allowed on the detail view (/api/resource/1/). This is because Django REST Framework needs to know what object you are looking to delete, and this information cannot be retrieved from just the list view.
If you need to connect http method DELETE with URL without pk in DRF try this inside of your ModelViewSet:
#action(methods=['delete'], detail=False)
def delete(self, request):
# your code
UPD: Note that action attribute inside of ModelViewSet class will be None due request. If you check it somewhere, handle not only action name, but request method and request path.

rails 4 - using cache with redirect_to

I'm trying to create GET URL that returns a resource located under 'public' folder, and i'm trying to use cache, to save redirects to the resource if not needed.
I have a table: 'ResourcesTable', that stores when was the last time that the resource was modified.
My route for the requested URL navigates to the controller that executes:
def handle_resource
resource_path = params(:resource)
last_updated_at = ResourcesTable.get_resource_timestamp(resource_path)
if stale?(:last_modified => last_updated_at.utc) then
redirect_to resource_path
The problem is, that its always goes to the 'redirect_to'.
I've checked with cURL, and the last_modify element in the header is the same as 'last_updated_at' returned from the DB.
Does anyone can help to make sure that it will do only one time the 'redirect_to', and takes the resource from cache the next time?
Thanks
Answered my own question.
In cURL - we should insert the date of the HTTP request:
curl -z 'Sun, 06 Nov 2024 08:49:37 GMT' -k -I -X GET URL_PATH
and that is how I can see when the 'stale?' method returns true or not.
In addition -
The controller should not return any message in case that 'stale?' returns False.

Serve images with django-rest-framework

I am trying to serve images from an api based on django-rest-api.
So far I have a very basic api view that loads an image and its mimetype and returns it.
#api_view(['GET'])
def get_pic(request, pk=None, format=None):
//get image and mimetype here
return HttpResponse(image, content_type=mimetype)
This has been working fine, however I have tested it on some new image libraries on iOS and have found that the API is returning a 406 error.
I believe this is because the client is sending a Accept image/* which this api view doesn't except.
Doing a HEAD on the api returns the following;
GET, OPTIONS
Connection → keep-alive
Content-Type → application/json
Date → Wed, 17 Jun 2015 10:11:07 GMT
Server → gunicorn/19.2.1
Transfer-Encoding → chunked
Vary → Accept, Cookie
Via → 1.1 vegur
X-Frame-Options → SAMEORIGIN
How can I change the Content-Type for this API to accept image requests?
I Have tried adding a custom parser with the right media_type but his doesn't seem to help. Is this the right approach or is there an easier way to serve images from django-rest-framework?
You need to create a custom renderer like:
class JPEGRenderer(renderers.BaseRenderer):
media_type = 'image/jpeg'
format = 'jpg'
charset = None
render_style = 'binary'
def render(self, data, media_type=None, renderer_context=None):
return data

Unexpected error 500 when returning response in Django, what's going on?

I have a view in Django that returns error 500 and I can't figure out why. It looks something like that:
def some_view(request):
result = some_func(request.raw_post_data)
response = HttpResponse(status=200)
response['Content-Type'] = 'application/json'
response.content = simplejson.dumps(result)
# if I log something here, it will be printed, so control reaches here
return response
So it looks like my view is working correctly and something then happens in Django internals, but I'm unable to trace where exactly it happens. Any hint on what it is or how to find it?
Things that might be important:
I'm running Python 2.5 and Django 1.1.4
POST data contains a JSON array with around 1000 string entries, 50 bytes each
the response is around 100KiB
other views seem to work pefectly fine
DB operations are involved
The problem was that FastCGI module in Apache has 30s timeout and it took more than 30s for Django to prepare the response. Apache then returned the generic 500 error message.

Setting persistent cookie from Java doesn't work in IE

All,
Although I see related topics on the forum, but I don't see a clear solution on this issue.
I am trying to set a javax.servlet.http.Cookie with an expiration time (so that it persists across browser sessions). Code:
public void respond(HttpServletRequest req, HttpServletResponse resp) {
int expiration = 3600;
Cookie cookie = new Cookie("TestCookie", "xyz");
cookie.setDomain("");
cookie.setVersion(0);
cookie.setPath("/");
cookie.setMaxAge(expiration);
cookie.setSecure(false);
resp.addCookie(cookie);
}
I don't see this cookie being set when I check in IE developer tools. Searching on the internet gave me clues that IE doesn't consider Max-Age, but only works with Expires. If this does not work for IE, then is there a proven way of setting the HTTP response headers for a persistent cookie so that it works for IE?
PS: This works fine on all other browsers.
I tried creating a string for the cookie having expires attribute. IE succeeded in creating it, but it lost the domain (default - "") and showed ".com" and turned it into a session cookie instead of a persistent cookie. This again works fine on all other browsers.
Please help.
Thanks.
Working with IE9, I found that it was the HttpOnly attribute that was required in order to get it to echo the cookie value on subsequent posts, e.g:
Set-Cookie: autologCk1=ABCD; Path=/autolog/; HttpOnly
The answer is at Persistent cookies from a servlet in IE.
Your case may be a different flavour of the same issue: that is, by prefixing the domain with a "." (which I'm pretty sure is a version 1 cookie feature), something in the Java stack decides it's a version 1 cookie (unrecognized and not persisted by IE, even IE8) and sends that cookie format.
Or, as that answer suggests, is there something in your cookie value that contains an unrecognized character?
As javax.servlet.http.Cookie does not allow you to set Expires attribute to the cookie, you should set it manually.
You also need to know that Expires must be specified in the form of Wdy, DD Mon YYYY HH:MM:SS GMT following RFC-2616 Full Date section (more info).
In Java you can do it this way:
public void respond(HttpServletRequest req, HttpServletResponse resp) {
int expiration = 3600;
StringBuilder cookie = new StringBuilder("TestCookie=xyz; ");
DateFormat df = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss 'GMT'", Locale.US);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 3600);
cookie.append("Expires=" + df.format(cal.getTime()) + "; ");
cookie.append("Domain=; ");
cookie.append("Version=0; ");
cookie.append("Path=/; ");
cookie.append("Max-Age=" + expiration + "; ");
cookie.append("Secure; ");
resp.setHeader("Set-Cookie", cookie.toString());
}