本文概述
什么是REST?
代表性状态传输(REST)是基于HTTP的轻量级服务器, 可在类似于“常规”网站的网络服务器上运行。而不是以表示和数据的组合形式交付的HTML, 而是使用分隔符和分隔符(如JSON)以最小的格式显示数据。可以将其视为用于设计联网应用程序的体系结构样式, 或者将其视为交付Web服务的一种方式。 REST是可浏览的, 因此可以帮助开发人员修改和检查其代码的正确性, 因为只有数据显示在浏览器中。这是一种提供服务或访问数据的更安全的方法, 因为它不会暴露网站使用的数据库的不必要的表面积。一些著名的REST API来自Twitter和Facebook Graph。
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.py
marine/
__init__.py
settings.py
urls.py
wsgi.py
你可以通过执行以下命令检查一切是否按预期进行:
$ python manage.py runserver
这将启动Django开发网络服务器进行测试。成功后, 你将看到:
Performing system checks...
0 errors found
February 15, 2015 - 15:50:53
Django 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__.py
admin.py
migrations/
__init__.py
models.py
tests.py
views.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 Fish
admin.site.register(Fish)
我们将使用创建的帐户登录到管理页面。启动开发服务器:
$ python manage.py runserver
打开127.0.0.1:8000/admin, 然后输入超级用户ID和密码。你应该会看到带有“海军陆战队”列表的管理页面。单击Fishs添加或修改数据。添加一些数据。
至此, 我们已经建立了一个正常运行的Django网站。现在, 我们将通过下载并安装djangorestframework将其合并到站点中。要记住的一件事是将rest_framework添加到marine / settings.py中的INSTALLED_APPS列表中, 并将urls.py更改为
from django.contrib import admin
from rest_framework import routers
from fishes import views
router = routers.DefaultRouter()
#makes sure that the API endpoints work
router.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 Fish
from rest_framework import serializers
class FishSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Fish
fields = ('name', 'active', 'created')
在views.py文件中, 添加:
from rest_framework import viewsets
from rest_framework import permissions
from fishes.models import Fish
from fishes.serializers import FishSerializer
# Create your views here.
class FishViewSet(viewsets.ModelViewSet):
# this fetches all the rows of data in the Fish table
queryset = Fish.objects.all()
serializer_class = FishSerializer
现在, 如果你打开http://127.0.0.1:8000/api/fishes/, 你将看到可浏览的API。
HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: 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。确保在检查器中, 选中“选定的表视图控制器的是初始视图控制器”复选框。
–在Main.storyboard中, 展开“表视图控制器”以显示“表视图单元格”, 选择“属性”检查器, 然后输入FishCell作为标识符。这会将Interface Builder故事板上的单元格链接到代码。 –将样式从基本更改为字幕。这使我们可以显示由cell.detailTextLabel设置的值。 –在“表视图控制器”场景下选择“表视图控制器”, 单击“身份检查器”, 然后在“自定义类”>“类”中输入TableViewController。这会将整个场景链接到TableViewController.m文件。
接下来, 我们添加使该应用程序执行某些操作的代码。该代码演示了如何使用简单的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 show
return 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 stage
NSArray *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 future
NSMutableString *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 object
fishJson = [NSJSONSerialization
JSONObjectWithData:response
options:kNilOptions
error:&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应用程序的代码。本教程包含许多“现实世界”应用程序中常见的概念和组件。如果你遇到任何问题或有任何疑问或意见, 请在下面的评论中告诉我。
评论前必须登录!
注册