I have a Django backend platform in which I implemented an API using django-rest-framework.
I have an iOS app in which I use AFNetworking2.0 to interact with my API, both using GET and POST, depending on the situation.
When I'm running the whole platform in local (using the Django internal runserver), everything works fine.
When running the backend with Apache, an strange problem happens. The first request (no matter GET or POST) my iOS app makes to any method handled by django-rest-framework ends up in a 302 redirect to the same method, but losing all the parameters. For example, this the log of Apache for my method "districts":
With GET: 189.122.X.X - - [07/May/2014:14:16:50 +0200] "GET /recursos/api/districts/?city_id=3 HTTP/1.1" 302 548 189.122.X.X - - [07/May/2014:14:16:51 +0200] "GET /recursos/api/districts/ HTTP/1.1" 200 399
And with POST: 189.122.X.X - - [07/May/2014:14:16:15 +0200] "POST /recursos/api/districts/ HTTP/1.1" 302 548 189.122.X.X - - [07/May/2014:14:16:16 +0200] "GET /recursos/api/districts/ HTTP/1.1" 200 399
Some interesting tests:
I don't know what else to do in order to get this working in all those scenarios.
For it to work right now, I have to make a first call that I know it will fail. And wait some seconds until doing the second, that will work. Because doing it immediately it will fail again.
The AFNetworking call looks like:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSString *method = [NSString stringWithFormat:@"%@%@", SERVER_URL, @"ws_districts"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@"3" forKey:@"city_id"];
[manager GET:method
parameters:dict
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"%@ %i",responseObject,city.o_id);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
In the django-rest-framework I use a serializer:
class DistrictSerializer(serializers.ModelSerializer):
class Meta:
model = District
fields = ('id', 'name')
A method in my view:
@csrf_exempt
def districts(request):
if request.method == 'GET':
city_id = request.GET.get('city_id', None)
queryset = District.objects.filter(city_id=city_id)
serializer_context = {'request': request}
serializer = DistrictSerializer(queryset, context=serializer_context)
response = JSONResponse(serializer.data)
return response
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = DistrictSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data, status=201)
return JSONResponse(serializer.errors, status=400)
And the url:
urlpatterns = patterns('views.api',
url(r'^api/districts/$', 'districts'),
Any hint?
I finally found the problem some time ago: it was all related to the HTTP Accept-Language header.
Our Django app defines the following languages:
LANGUAGES = (
('en', ugettext('En')),
('pt', ugettext('Pt')),
('es', ugettext('Es')))
When sending the request without specifying the AcceptLanguage header, it would end up on a 302.
By sending the request with "en-US,en;q=0.8,pt;q=0.6,es;q=0.4", it works fine.