如何将 XML POST 数据从 iOS 应用程序发送到 Django 应用程序?

发布于 2024-11-05 13:36:08 字数 4495 浏览 0 评论 0 原文

我正在尝试在 iOS 游戏应用程序中实现在线排行榜,使用 Django 处理来自 iDevice 的 POST 请求并存储分数。我已经弄清楚如何让 Django 将对象序列化为 XML,并且我的 iPhone 可以读取并显示分数。然而,我一生都无法让我的 iPhone 将 XML POST 到我的 Django 服务器。

下面是我用来发布分数的函数...

iOS (Objective-C) 控制器:

- (void) submitHighScore {
    NSLog(@"Submitting high score...");

    NSString *urlString = HIGH_SCORES_URL;
    NSURL *url = [NSURL URLWithString: urlString];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
    [request setHTTPMethod: @"POST"];
    [request setValue: @"text/xml" forHTTPHeaderField: @"Content-Type"];

    NSMutableData *highScoreData = [NSMutableData data];
    [highScoreData appendData: [[NSString stringWithFormat: @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"<player_name>%@</player_name", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"<score>%d</score>", 0] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"</xml>"] dataUsingEncoding: NSUTF8StringEncoding]];
    [request setHTTPBody: highScoreData];

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request 
                                                                  delegate: self];
    if (!connection) {
        NSLog(@"Request to send high scores appears to be invalid.");
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
    }
}

上述方法成功发送请求,并将其正确解释为 CONTENT_TYPE: text/xml,但是处理请求的 Django 视图似乎无法理解它,几乎将其解释为纯文本。下面是我的 Django 视图...

Django (Python) 视图:

from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core import serializers
from django.core.exceptions import ValidationError
from django.views.decorators.csrf import csrf_exempt

from modologger.taptap.models import HighScore

@csrf_exempt
def leaderboard( request, xml = False, template_name = 'apps/taptap/leaderboard.html' ):
    """Returns leaderboard."""
    if xml == True: # xml is set as True or False in the URLConf, based on the URL requested
        if request.method == 'POST':
            postdata = request.POST.copy()
            print postdata
                # here, postdata is evaluated as: 
                # <QueryDict: {u'<?xml version': [u'"1.0" encoding="UTF-8" ?><player_name>test</player_name<score>0</score></xml>']}>
            for deserialized_object in serializers.deserialize('xml', postdata):    # this fails, returning a 500 error
                try:
                    deserialized_object.object.full_clean()
                except ValidationError, e:
                    return HttpResponseBadRequest
                deserialized_object.save()
        else:   
            high_score_data = serializers.serialize( 'xml', HighScore.objects.all() )
            return HttpResponse( high_score_data, mimetype = 'text/xml' )
    else:
        high_scores = HighScore.objects.all()
        return render_to_response( template_name, locals(), context_instance = RequestContext( request ) )

说实话,我不确定问题出在 Objective-C 还是 Django 代码中。 Objective-C 是否未以正确的格式发送 XML?或者 Django 服务器没有正确处理该 XML?

任何见解将不胜感激。提前致谢。

更新:

我让它工作,通过编辑 iOS 控制器来设置请求的 HTTPBody,如下所示:

NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: @"player_name=%@;", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: @"score=%d", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];

出于某种原因,在其中放置一个分号让 Django 识别它,将值分配给 HighScore 类的新实例,然后保存它。测试服务器上的日志记录表明 request.POST

仍然不太确定这一切是怎么回事。

根据Radu的建议,我用 NSLog 查看了 highScoreData,在将其附加到 request.HTTPBody 后,立即查看结果是 <706c6179 65725f6e 616d653d 74657374 3b73636f 72653d39>

我是一个巨大的 Obj-C 菜鸟,所以再次感谢任何帮助!再次感谢。

I am attempting to implement an online leaderboard in a game app for iOS, using Django to process POST requests from the iDevice and store the scores. I have figured out how to get Django to serialize the objects to XML, and my iPhone can read and display the scores. However, I can't for the life of me get my iPhone to POST XML to my Django server.

Below is the function I am using to post the scores...

iOS (Objective-C) Controller:

- (void) submitHighScore {
    NSLog(@"Submitting high score...");

    NSString *urlString = HIGH_SCORES_URL;
    NSURL *url = [NSURL URLWithString: urlString];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
    [request setHTTPMethod: @"POST"];
    [request setValue: @"text/xml" forHTTPHeaderField: @"Content-Type"];

    NSMutableData *highScoreData = [NSMutableData data];
    [highScoreData appendData: [[NSString stringWithFormat: @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"<player_name>%@</player_name", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"<score>%d</score>", 0] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"</xml>"] dataUsingEncoding: NSUTF8StringEncoding]];
    [request setHTTPBody: highScoreData];

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request 
                                                                  delegate: self];
    if (!connection) {
        NSLog(@"Request to send high scores appears to be invalid.");
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
    }
}

The above method succeeds in sending the request, and interprets it correctly as CONTENT_TYPE: text/xml, but the Django view that processes the request can't seem to make any sense of it, interpreting it almost as if it was merely plain text. Below is my Django view...

Django (Python) view:

from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core import serializers
from django.core.exceptions import ValidationError
from django.views.decorators.csrf import csrf_exempt

from modologger.taptap.models import HighScore

@csrf_exempt
def leaderboard( request, xml = False, template_name = 'apps/taptap/leaderboard.html' ):
    """Returns leaderboard."""
    if xml == True: # xml is set as True or False in the URLConf, based on the URL requested
        if request.method == 'POST':
            postdata = request.POST.copy()
            print postdata
                # here, postdata is evaluated as: 
                # <QueryDict: {u'<?xml version': [u'"1.0" encoding="UTF-8" ?><player_name>test</player_name<score>0</score></xml>']}>
            for deserialized_object in serializers.deserialize('xml', postdata):    # this fails, returning a 500 error
                try:
                    deserialized_object.object.full_clean()
                except ValidationError, e:
                    return HttpResponseBadRequest
                deserialized_object.save()
        else:   
            high_score_data = serializers.serialize( 'xml', HighScore.objects.all() )
            return HttpResponse( high_score_data, mimetype = 'text/xml' )
    else:
        high_scores = HighScore.objects.all()
        return render_to_response( template_name, locals(), context_instance = RequestContext( request ) )

To be honest, I'm not sure whether the problem lies in the Objective-C or in the Django code. Is the Objective-C not sending the XML in the right format? Or is the Django server not processing that XML correctly?

Any insight would be much appreciated. Thanks in advance.

Update:

I got it to work, by editing the iOS Controller to set the HTTPBody of the request like so:

NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: @"player_name=%@;", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: @"score=%d", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];

For some reason putting a semicolon in there got Django to recognize it, assign the values to a new instance of a HighScore class, and save it. The logging on the test server indicates request.POST is <QueryDict: {u'score': [u'9'], u'player_name': [u'test']}>.

Still not quite sure what to make of all this.

As per Radu's suggestion, I took a look at highScoreData with NSLog, right after appending it to request.HTTPBody, and the result is <706c6179 65725f6e 616d653d 74657374 3b73636f 72653d39>.

I'm a huge Obj-C noob, so again, any help is appreciated! Thanks again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

转角预定愛 2024-11-12 13:36:08

由于您控制双方,因此我会降低 xml 编码数据的复杂性,并使用 RestKit 或其他一些框架来轻松与 Django 通信。

Since you control both sides, I'd drop the complexity of xml encoding the data and use RestKit or some other framework that makes it easy to communicate with Django.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文