移动应用程序构建简单的REST API

本文概述

  • 什么是REST?
  • HTTP方法和API端点
  • 使用djangorestframework构建简单的REST API
  • iOS移动应用
什么是REST? 代表性状态传输(REST)是基于HTTP的轻量级服务器, 可在类似于“常规”网站的网络服务器上运行。而不是以表示和数据的组合形式交付的HTML, 而是使用分隔符和分隔符(如JSON)以最小的格式显示数据。可以将其视为用于设计联网应用程序的体系结构样式, 或者将其视为交付Web服务的一种方式。 REST是可浏览的, 因此可以帮助开发人员修改和检查其代码的正确性, 因为只有数据显示在浏览器中。这是一种提供服务或访问数据的更安全的方法, 因为它不会暴露网站使用的数据库的不必要的表面积。一些著名的REST API来自Twitter和Facebook Graph。
【移动应用程序构建简单的REST API】REST是平台和语言独立的。你可以使用通常与网站创建相关的任何语言(例如PHP, Python或Ruby)编写REST API。 REST体系结构中使用了四种通常定义的方法。这些是创建, 读取, 更新和删除(CRUD)方法。也可以添加更专业的方法, 例如检索最受欢迎的前十项或所有用户的高分。这可以通过编写新方法或使用查询参数(例如/ api / items?top = 10)来实现。
HTTP方法和API端点 你可能还记得创建Web表单(同步)或Ajax请求(异步)调用时曾使用过GET和POST请求。 PUT和DELETE请求较少使用。然后, 如果你使用PHP, Python或其他语言编写了一个处理表单数据的应用程序, 那么你已经编写了自己的简单REST框架。 POST, GET, PUT和DELETE对应于创建, 读取, 更新和删除, 并且与基本数据库操作有关。 API端点描述了服务公开的数据上的可用操作。可以将它们视为提供数据的URL(GET请求)或可以向其提交数据的URL(POST请求)。可以使用许多数据格式, 但更常见的是JSON和XML。即使多次应用, GET / api / boats / 123456也会返回ID为123456的小船上的数据。
使用djangorestframework构建简单的REST API 我们将使用Django(Python MVC框架)和djangorestframework。 Djangorestframework是使用django(python)构建的, 专门用于通过REST框架公开数据。
首先, 你需要安装Python v2.7或更高版本以及Django 1.7.4或更高版本。如果不这样做, 请立即安装Python和Django。
你可以通过启动命令行并键入python命令来测试安装。一切顺利, 你应该看到版本信息。继续输入:
> > > import django> > > print(django.get_version())1.7.4

这验证你的系统上安装了Django。接下来, 我们构建Django项目:
$ django-admin.py startproject marine

这是创建的文件和文件夹的列表。
marine/manage.pymarine/__init__.pysettings.pyurls.pywsgi.py

你可以通过执行以下命令检查一切是否按预期进行:
$ python manage.py runserver

这将启动Django开发网络服务器进行测试。成功后, 你将看到:
Performing system checks...0 errors foundFebruary 15, 2015 - 15:50:53Django version 1.7.4, using settings 'mysite.settings'Starting development server at http://127.0.0.1:8000/Quit the server with CONTROL-C.

如果你打开URL http://127.0.0.1:8000/, 你将看到一个占位符网站。
现在, 我们有了该网站的裸露骨架。接下来, 我们将构建一个包含模型的应用程序(容器)(如在Model-View-Controller中一样)。模型是应用程序数据的来源。
输入:
$ python manage.py startapp fishes

将导致以下文件
fishes/__init__.pyadmin.pymigrations/__init__.pymodels.pytests.pyviews.py

在models.py文件中, 有django.db导入模型的导入行。向其添加以下代码。
class Fish(models.Model):name = models.CharField(max_length=255)created = models.DateTimeField('auto_now_add=True')active = models.BooleanField()

这将创建一个类, 该类公开鱼的名称, 创建日期以及数据行是否处于活动状态。你可以通过参考相关文档来更改字段类型。
现在, 将fishs应用添加到marine / settings.py文件中进行注册。通过在INSTALLED_APPS下执行此操作, 将鱼添加到列表中。运行python manage.py sql fish来查看我们激活应用程序时将运行的数据库模式SQL的预览。
BEGIN; CREATE TABLE "fishes_fish" ("id" integer NOT NULL PRIMARY KEY, "name" varchar(255) NOT NULL, "created" datetime NOT NULL, "active" bool NOT NULL); COMMIT;

要确认在默认sqlite数据库中创建了相关表, 请在旧版Django上键入python manage.py migration或python manage.py syncdb。 Django默认会创建身份验证表, 并在sqlite3数据库中创建空的fishes_fish表。提示符将询问你是否要创建超级用户, 因为这是你第一次运行Django。
如果由于某种原因没有提示你创建超级用户, 请在命令提示符下键入:
$ python manage.py createsuperuser

按照说明创建管理员帐户。 Django提供了一个内置的管理页面, 可让你插入和修改数据。需要通过编辑fishes文件夹中的admin.py文件来激活该功能。从django.contrib import admin之后添加以下代码
...from fishes.models import Fishadmin.site.register(Fish)

我们将使用创建的帐户登录到管理页面。启动开发服务器:
$ python manage.py runserver

打开127.0.0.1:8000/admin, 然后输入超级用户ID和密码。你应该会看到带有“海军陆战队”列表的管理页面。单击Fishs添加或修改数据。添加一些数据。
移动应用程序构建简单的REST API

文章图片
至此, 我们已经建立了一个正常运行的Django网站。现在, 我们将通过下载并安装djangorestframework将其合并到站点中。要记住的一件事是将rest_framework添加到marine / settings.py中的INSTALLED_APPS列表中, 并将urls.py更改为
from django.contrib import adminfrom rest_framework import routersfrom fishes import viewsrouter = routers.DefaultRouter()#makes sure that the API endpoints workrouter.register(r'api/fishes', views.FishViewSet)admin.autodiscover()urlpatterns = patterns('', # Examples:# url(r'^$', 'marine.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')))

这段代码打开了对`djangorestframework至关重要的API路由, 并使用正则表达式来设置站点的有效URL。
当我们安装djangorestframework时, 它使我们能够使用序列化程序, 该序列化程序将从fish模型获得的数据展平为XML或JSON字符串格式。要为fishes模型创建序列化器, 我们在fishes文件夹下创建一个文件, 并将其命名为serializers.py。这是该文件的内容:
from fishes.models import Fishfrom rest_framework import serializersclass FishSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = Fishfields = ('name', 'active', 'created')

在views.py文件中, 添加:
from rest_framework import viewsetsfrom rest_framework import permissionsfrom fishes.models import Fishfrom fishes.serializers import FishSerializer# Create your views here.class FishViewSet(viewsets.ModelViewSet):# this fetches all the rows of data in the Fish tablequeryset = Fish.objects.all()serializer_class = FishSerializer

现在, 如果你打开http://127.0.0.1:8000/api/fishes/, 你将看到可浏览的API。
HTTP 200 OKContent-Type: application/jsonVary: AcceptAllow: GET, POST, HEAD, OPTIONS[{"name": "Dory", "created": "2014-06-21T04:23:01.639Z", }, {"name": "Angel", "created": "2014-07-21T04:23:01.639Z", }, {"name": "Clown", "created": "2014-08-21T04:23:01.639Z", }]

你可以在GitHub上找到REST API应用程序的源代码。没有数据, 因此下载后, 你将需要在旧版Django上运行python manage.py migration或python manage.py syncdb。
iOS移动应用 接下来, 我们将完成创建从API接收数据的移动应用所需的关键步骤。我们正在使用UITableView在列表中显示数据。在XCode 6.3.1(撰写本文时为最新版本)中, 创建一个新项目
文件> 新建> 项目> iOS应用程序> 单视图应用程序
  • 产品名称:鱼
  • 语言:Objective-C
  • 设备:iPhone(默认为通用, 包括iPhone和iPad)
  • 暂时不使用核心数据。
选择一个位置来保存你的项目, 然后单击“创建”。我们将处理Fishes文件夹中包含的文件。
默认情况下, 该项目具有一个View Controller。我们希望将REST API中的数据显示为列表, 因此将改用Table View Controller。创建一组新的Objective-C文件(“文件”> “新建”> “文件”> “ iOS源”> “ Cocoa Touch类”)。
  • 类:TableViewController
  • 子类:UITableViewController
  • 我们不需要XIB文件
将这些新文件保存在Fishes文件夹中。
打开Main.storyboard, 转到“对象库”, 然后将“ Table View Controller”对象拖到情节提要中。选择并删除默认的View Controller。确保在检查器中, 选中“选定的表视图控制器的是初始视图控制器”复选框。
移动应用程序构建简单的REST API

文章图片
–在Main.storyboard中, 展开“表视图控制器”以显示“表视图单元格”, 选择“属性”检查器, 然后输入FishCell作为标识符。这会将Interface Builder故事板上的单元格链接到代码。 –将样式从基本更改为字幕。这使我们可以显示由cell.detailTextLabel设置的值。 –在“表视图控制器”场景下选择“表视图控制器”, 单击“身份检查器”, 然后在“自定义类”> “类”中输入TableViewController。这会将整个场景链接到TableViewController.m文件。
移动应用程序构建简单的REST API

文章图片
接下来, 我们添加使该应用程序执行某些操作的代码。该代码演示了如何使用简单的NSArray显示在TableViewController.m中进行硬编码的数据。用以下内容替换所有现有功能。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {#warning Potentially incomplete method implementation.// Return the number of sections.return 1; }- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {#warning Incomplete method implementation.// Return the number of rows in the section.I currently have three rows we would like to showreturn 3; }- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FishCell" forIndexPath:indexPath]; //temporary data to demonstrate the structure of a NSDictionary in an NSArray, which is the general structure of a JSON, this can be removed in a later stageNSArray *fishes = @[@{@"name": @"Dory", @"created": @"2014-06-21T04:23:01.639Z"}, @{@"name": @"Angel", @"created": @"2014-07-21T04:23:01.639Z"}, @{@"name": @"Clown", @"created": @"2014-08-21T04:23:01.639Z"}]; if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"FishCell"]; }//We will replace fishes with fishJson once we have code that downloads from the REST api[cell.textLabel setText:[[fishes objectAtIndex:indexPath.row] objectForKey:@"name"] ]; [cell.detailTextLabel setText:[[fishes objectAtIndex:indexPath.row] objectForKey:@"created"]]; return cell; }

现在, 我们可以测试这个简单的应用程序。选择产品> 运行。
接下来, 我们需要从使用djangorestframework发布的REST API中获取JSON。我们通过在接口级别进行注册并将其与@ propertyand @ synthesize进行合成, 从而建立了一个名为fishJson的NSArray对象。这将替换setter和getter的代码。然后, 我们替换在numberOfRowsInSection中拥有的代码, 在这里我们将fishs替换为fishJson, 后者包含来自REST API的JSON。再次替换任何现有的函数或声明。
@interface TableViewController ()@property (strong) NSArray *fishJson; @end@implementation TableViewController@synthesize fishJson; - (void) downloadData {//I use NSMutableString so we could append or replace parts of the URI with query parameters in the futureNSMutableString *remoteUrl = [NSMutableString stringWithFormat:@"http://127.0.0.1:8000/api/fishes/?format=%@", @"json"]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:remoteUrl] ]; NSError *jsonError = nil; NSHTTPURLResponse *jsonResponse = nil; NSData *response; do {response = [NSURLConnection sendSynchronousRequest:request returningResponse:& jsonResponse error:& jsonError]; } while ([jsonError domain] == NSURLErrorDomain); if([jsonResponse statusCode] != 200) {NSLog(@"%ld", (long)[jsonResponse statusCode]); } else {NSLog(@"%@", @"200 OK"); }NSError* error; if(response) {//fishJson was defined earlier near the top as a NSArray objectfishJson = [NSJSONSerializationJSONObjectWithData:responseoptions:kNilOptionserror:& error]; }}

我们需要确保该方法在应用启动时运行, 并在viewDidLoad下面添加以下内容:
[self downloadData];

在这里, 我们更新numberOfRowsInSection方法。此代码确保行数与fishJson数组中包含的元素数匹配。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {#warning Incomplete method implementation.// Return the number of rows in the section.return [fishJson count]; }

更新cellForRowAtIndexPath方法, 以便它从REST提要中加载条目:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FishCell" forIndexPath:indexPath]; // Configure the cell...if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"FishCell"]; }[cell.textLabel setText:[[fishJson objectAtIndex:indexPath.row] objectForKey:@"name"] ]; [cell.detailTextLabel setText:[[fishJson objectAtIndex:indexPath.row] objectForKey:@"created"]]; return cell; }

现在, 我们有了一个可以运行的简单移动应用程序, 以显示从在线或本地REST API获取的数据。你可以在上面的同一存储库中找到iOS应用程序的代码。本教程包含许多“现实世界”应用程序中常见的概念和组件。如果你遇到任何问题或有任何疑问或意见, 请在下面的评论中告诉我。

    推荐阅读