注册本站  论坛  繁體中文

电脑技巧
手机 | MP3 | MP4 | 显卡 | 主板 | 显示器 | 光存储 | 笔记本 | 网络设备 | 移动存储 | 数码相机
键鼠 | CPU | 音箱 | GPS | 电视 | 服务器 | 投影机 | 机箱电源 | 品牌电脑 | 办公打印 |
| 网站首页 | Cisco | Windows | Linux | Java | Dotnet | Oracle | 网页设计 | 平面设计 | 安全 | 软件应用 | 电脑维修 | 办公维修 |
您现在的位置: 电脑技巧 >> Linux >> Linux编程 >> Python编程 >> Linux正文

使用TurboGears和Python开发Web 站点

文章来源:ChinaITLab收集整理 作者:Ian Maur… 更新时间:2006-9-22 【 】 【加入收藏

2006 年 9 月 18 日

本 系列 文章一共有两篇,本文是第二篇。在本文中,我们将展示 TurboGears 的用法,它是另外一个基于 Python 的 MVC 风格的 Web 应用程序框架。在第一篇文章中我们介绍了 Django 框架,本文将介绍如何使用 TurboGears 来创建一个基于 Web 的应用程序,并将对 Turbogears 和 Django 进行比较。

TurboGears 开发人员称这个项目是一个 “大框架(megaframework)”,这是因为它是由现有的子项目构成的。TurboGears 可以帮助将很多主要组件集成在一起:

  • MochiKit:JavaScript 库
  • Kid:模板语言
  • CherryPy:基本 Web 框架
  • SQLObject:对象关系映射器(ORM)

安装 TurboGears

    使用 TurboGears 的第一个步骤是确保我们已经安装了 Python。TurboGears 的最新版本需要 Python 2.4。请参见 参考资料 中 Python 主页的链接。

    Setuptools 是 Python 社区开发的一个新项目,它可以更方便地安装并更新 Python 软件。软件以归档文件的形式进行打包,称为 Egg,这与 Java™ 的 JAR 文件或 Ruby GEM 文件类似,可以使用一个名为 easy_install 的工具下载并安装。

    TurboGears 是第一个使用 setuptools 工具来进行分发和安装的大型 Python 项目。请参见 参考资料 中 setuptools 页面的链接和 TurboGears 的下载页面。

    本文使用了撰写本文时最新的开发版本(0.9a5),这可以通过 preview 的下载页面得到:

  easy_install -f http://www.turbogears.org/preview/download/index.html TurboGears

    要获得最新版本的 TurboGears(目前是 0.8.9),我们可以简单地删除 -f 选项和 preview 站点的 URL:

easy_install TurboGears

检查 TurboGears 管理工具

    在安装 TurboGears 之后,我们就应该有了管理工具 tg-admin,它在您自己的目录中。我们可以在命令行中输入 tg-admin 查看它是否存在:


清单 1. 使用 TurboGears 管理工具
~/dev$ tg-admin

TurboGears 0.9a5 command line interface

Usage: /usr/bin/tg-admin [command] [options]

Available commands:

      i18n  Manage i18n data

      info  Show version info

quickstart  Create a new TurboGears project

     shell  Start a Python prompt with your database available

       sql  Run the SQLObject manager

   toolbox  Launch the TurboGears Toolbox

    update  Update an existing turbogears project

      

快速启动

    要启动 TurboGears 项目,我们需要使用 tg-admin quickstart 功能。我们会被要求提供一个项目名和一个目录名。对于本文来说,我创建了一个简单的购物车,名为 TG Commerce,它有一个名为 tgcommerce 的包:


清单 2. 启动 TurboGears 项目
~/dev$ tg-admin quickstart

Enter project name: TG Commerce

Enter package name [tgcommerce]:

Selected and implied templates:

  turbogears#turbogears  web framework

Variables:

  package:  tgcommerce

  project:  TG-Commerce

Creating template turbogears

  Creating ./TG-Commerce/

    ... (output snipped) ...

      

    TurboGears 使用下面的 tgcommerce 包创建一个 TG-Commerce 项目。我们现在可以启动这个项目提供的测试服务器了:

 


清单 7. 使用 “tg-admin sql sql” 命令查看数据库模式


~/dev/TG-Commerce$ tg-admin sql sql

Using database URI sqlite:///home/ubuntu/dev/TG-Commerce/tgcommerce.db

CREATE TABLE category (

    id INTEGER PRIMARY KEY,

    name VARCHAR(64),

    parent_id INT

);

CREATE TABLE product (

    id INTEGER PRIMARY KEY,

    name VARCHAR(64),

    sku VARCHAR(64),

    price DECIMAL(10, 2) NOT NULL,

    category_id INT

);

      


    下面是 OrderOrderItem 类,它们分别用来保存购物车和所购物品清单。由于 order 是一个 SQL 关键字,因此 Order 类的表名被使用 sqlmeta 子类的表属性重新定义为 orders


清单 8. Order 和 OrderItem 类(model.py,续)

class Order(SQLObject):

    items = MultipleJoin('OrderItem', joinColumn='order_id')

    class sqlmeta:

        table = 'orders'

class OrderItem(SQLObject):

    quantity = IntCol(notNone=True)

    price = CurrencyCol(notNone=True)

    total = CurrencyCol(notNone=True)

    order = ForeignKey('Order')

    product = ForeignKey('Product')

      

使用 tg-admin sql create 命令创建数据库表:


清单 9. 使用 “tg-admin sql create” 命令创建数据库表

~/dev$ tg-admin sql create

Using database URI sqlite:///home/ubuntu/dev/TG-Commerce/tgcommerce.db

      

    我们可以使用 tg-admin sql help 找到更多命令,包括删除表的命令。在使用这个命令时要特别小心,因为这会删除所有的表以及表中的数据。由于这个原因,在生产环境中应当锁定 tg-admin 命令。

使用 CatWalk 操纵模型

    从 0.9 版本开始,TurboGears 提供了一组名为 Toolbox 的工具,其中包含了一个名为 CatWalk 的模型浏览器。CatWalk 是为那些希望使用一个 GUI 工具来快速创建、更新和删除模型中数据的开发人员设计的。

Toolbox 可以作为一个单独的服务器启动,它可以使用 tg-admin 命令来运行:


清单 10. 使用 tg-admin 启动 toolbox 服务器

~/dev/TG-Commerce$ tg-admin toolbox

... (snip) ...

05/Mar/2006:15:01:33 HTTP INFO Serving HTTP on http://localhost:7654/

      

 

    如果浏览器没有自动打开这个地址,请手工输入 Toolbox 服务器所指定的 URL(http://localhost:7654/),并点击 CatWalk 链接打开 CatWalk。


图 1. CatWalk 工具
CatWalk 工具

    Toolbox 是面向开发人员的,而不是面向终端用户的,它最适合辅助完成数据模型化和为应用程序快速提供数据。我们可以使用 Ctrl-C 关闭 toolbox 服务器。在本文介绍中,我们将不会使用这个工具。

创建视图

     在 TurboGears 中创建视图的默认方法是使用 Kid XML 模板化语言。由于 Kid 使用了 XML,因此所有的模板都必须很好地进行格式化,否则在呈现时就会抛出异常。Kid 还可以支持模板继承(template inheritance),这样所生成的新模板就可以对基本模板进行扩充,从而可以在一个地方创建并维护通用代码。

    在 TurboGears 中,Kid 文件都位于 templates 目录中,扩展名为 .kid。默认情况下,有一个 master.kid 文件和一个 welcome.kid 文件,其中 master.kid 文件是基础模板文件,welcome.kid 在其 <html> 标记中使用 py:extends 属性对其进行了继承。

    要创建一个新模板,我建议您对 welcome.kid 文件进行拷贝或重命名,并使用它作为起点开始下一步的工作。对于本例来说,我们首先创建的是分类模板,它会显示有关给定分类的以下信息:

  • 分类名(title 和 breadcrumb)
  • 到祖先的链接(breadcrumb)
  • 到子分类的链接(list)
  • 到产品的链接(list)


清单 11. 分类页面 kid 模板文件(category.kid)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

    xmlns:py="http://purl.org/kid/ns#"

    py:extends="'master.kid'">

<head>

    <title>Category: ${category.name}</title>

</head>

<body>

 <div id="breadcrumbs">

  <ul>

  <li py:for="ancestor in list(category.ancestors)[::-1]">

    >

    <a href="/category/${ancestor.id}"

     py:content="ancestor.name"></a>

   </li>

   <li id="active">

    > <span py:replace="category.name" />

   </li>

  </ul>

 </div>

 <div id="subcategories" py:if="category.subcategories">

  <div class="header">Subcategories</div>

  <ul>

   <li py:for="subcategory in category.subcategories">

    <a href="/category/${subcategory.id}"

     py:content="subcategory.name"></a>

   </li>

  </ul>

 </div>

 <div id="subcategories" py:if="category.products">

  <div class="header">Products</div>

  <ul>

   <li py:for="product in category.products">

    <a href="/product/${product.id}"

     py:content="product.name"></a>

   </li>

  </ul>

 </div>

</body>

</html>

      

清单 11 展示了一些关键的 Kid 功能:

  • 使用 py:extends 继承 master.kid
  • 在 title 中使用 ${category.name} 进行表达式替换
  • 使用 py:for 遍历祖先、子分类和产品
  • 使用限制逻辑对在 breadcrumb 中显示的祖先进行反向
  • 使用 py:content 填充链接文本
  • 使用 py:replace 完全替换 span 标记

上面引用的 ancestors 属性要想有效,Category 模型类需要修改成包含一个 _get_ancestors 方法:

 


清单 12. 将 “ancestors” 属性的 “get” 方法添加到 Category 类中


class Category(SQLObject):

    name = StringCol(length=64)

    parent = ForeignKey('Category', default=None)

    subcategories = MultipleJoin('Category', joinColumn='parent_id')

    products = MultipleJoin('Product')

    def _get_ancestors(self):

 ancestor = self.parent

 while ancestor:

     yield ancestor

     ancestor = ancestor.parent

      


创建控制器

    TurboGears quickstart 提供了一个具有 controllers.py 模块的项目,该模块是 Root 控制器类所在的位置。这是应用程序的主入口点,也是添加新控制器方法的地方。

    下面是 TurboGears expose 中与分类 HTML 模板有关的两个样例控制器方法。控制器方法会返回字典,它们在对指定的 Kid 模板进行呈现时被用作名称空间或上下文。


清单 13. 控制器类

from turbogears import controllers, expose

class Root(controllers.Root):

    @expose("tgcommerce.templates.category")

    def index(self):

 from model import Category

 category = Category.selectBy(parent=None)[0]

 return dict(category=category)

    @expose("tgcommerce.templates.category")

    def category(self, categoryID):

 from model import Category

 category = Category.get(categoryID)

 return dict(category=category)

      

    在 TurboGears 中,URL 非常清楚地映射到方法上,它们都包含在 Root 控制器中。根 URL / 映射为一个名为 index 的特殊方法。通过向 Root 添加一个名为 category 的方法,它就可以通过 URL /category 进行访问了。任何提交的 URL 如果无法匹配给定方法,就会产生一个 404 错误,除非定义了一个 default 方法。

下面是一些可能的 URL 情况及其结果:

  • /:显示没有父 id 的第一个分类
  • /category?categoryID=2:显示 id 值为 2 的分类。
  • /category/1:显示 id 值为 1 的分类(格式为 TG 0.9)
  • /category:抛出一个 500 错误,这是因为缺少分类 id。
  • /xyz:抛出一个 404 错误

图 2 给出了分类显示的页面:


图 2. 分类显示
分类显示 

产品显示

     对于产品显示页面来说,我们要创建一个 product 控制器,它会从数据库中检索出一个产品,并将其传递给 product Kid 模板进行呈现。


清单 14. 增加产品控制器方法

@expose("tgcommerce.templates.product")

def product(self, productID):

    from model import Product

    product = Product.get(productID)

    return dict(product=product)

      

product.kid 模板有一个产品信息表。此处要注意用来显示价格(有两位小数)的 Python 字符串的格式:

 


清单 15. 分类页 kid 模板文件(product.kid)


<table id="product-info">

  <tr>

    <td class="fld">Name:</td>

    <td class="val"><span py:replace="product.name" /></td>

  </tr>

  <tr>

    <td class="fld">SKU:</td>

    <td class="val"><span py:replace="product.sku" /></td>

  </tr>

  <tr>

    <td class="fld">Price:</td>

    <td class="val">$<span py:replace="'%.2f' % product.price" /></td>

  </tr>

</table>

      


图 3 给出了产品显示页面:


图 3. 产品显示页面
产品显示页面 

错误处理

     控制器方法尚未考虑的一件事是 SQLObject 的 get 方法所抛出的 SQLObjectNotFound 异常。清单 16 给出了捕获这个异常并将其作为 NotFound 异常重新抛出的方法,这会发送一个基本的 HTTP 404 错误:


清单 16. 向 Controller 类添加的错误处理

from model import Category, Product

from sqlobject import SQLObjectNotFound

from cherrypy import NotFound

from turbogears import controllers, expose, url

class Root(controllers.Root):

    @expose("tgcommerce.templates.category")

    def category(self, categoryID):

 try:

     category = Category.get(categoryID)

 except SQLObjectNotFound:

     raise NotFound()

 return dict(category=category)

    @expose("tgcommerce.templates.product")

    def product(self, productID):

 try:

     product = Product.get(productID)

 except SQLObjectNotFound:

     raise NotFound()

 return dict(product=product)

      

     处理找不到对象的错误的另外一个策略不是发送 404 错误,而是对其进行重定向。这是使用 turbogears.redirect(...) 方法实现的:


清单 17. 重定向的例子

from turbogears import redirect

try:

    object = ClassName.get(objectID)

except SQLObjectNotFound:

    raise redirect("/path_to_redirect")

      

 

购物车

     为了有一个可以正常工作的购物车,我们需要启用会话来维护请求之间的状态。会话是在配置文件中通过将 session_filter.on 值设置为 True 来启用的。


清单 18. 在配置文件中启用会话(dev.cfg)

session_filter.on = True

sqlobject.dburi="notrans_sqlite:///path/to/devdir/TG-Commerce/tgcommerce.database"

server.environment="development"

autoreload.package="tgcommerce"

      

    要在每个页面上显示当前的购物车,我们可以将下面的 HTML 代码放到主模板文件中,而不用将其拷贝并粘贴到每个页面上:


清单 19. 主 kid 模板中包含的购物车(master.kid)

<html>

  <body>

  ...

 <div id="shopping-cart">

  Shopping Cart:

  <span id="cart-qty" py:content="cart.total_quantity" /> items

  ($<span id="cart-amt" py:content="'%.2f' % cart.total_price" />)

 </div>

  </body>

</html>

      

    上面这段模板的变化本身会失败,因为在从控制器方法返回的字典中没有 cart 值。清单 20 给出了为了将购物车包含到会话中要对 products 方法所做的修改。


清单 20. 从控制器返回的购物车对象

@expose("tgcommerce.templates.product")

def product(self, productID):

    try:

 product = Product.get(productID)

    except SQLObjectNotFound:

 raise NotFound()

    return self.results(product=product)

def results(self, cart=None, **kw):

    if not cart:

 cart = self.get_cart()

    kw['cart'] = cart

    return kw

def get_cart(self):

    cartID = session.get("cartID", None)

    cart = None

    if cartID:

 try:

     cart = Order.get(cartID)

 except SQLObjectNotFound:

     pass

    if cart is None:

 cart = Order()

 session["cartID"] = cart.id

    return cart

      

   results 方法会调用 get_cart,它会检索当前的 Order 对象,如果不存在或没有找到,就创建一个新对象。这些修改应该在 indexcategory 方法中都进行。

Ajax 添加购物车

     要让这个购物车可以更好地工作,产品的 add-to-cart 函数需要调用 Ajax,这样不用对页面进行刷新。对于不了解 Ajax 的人来说,Ajax 就是一种 Web 实现模式,它代表 Asynchronous JavaScript + XML。最初对 Ajax 术语进行定义的文章请参见 参考资料。

     这个例子使用了 JavaScript Object Notation(JSON)作为传输格式,而没有使用 XML。JSON 是一种更为轻量级的技术,TurboGears 和 MochiKit 都可以很好地支持这项技术。尽管异步 JavaScript 和 JSON 技术的应用日益流行,但是它的广泛使用却使人们更多地记住了 Ajax 的名字,因为这样比较简单,而 Ajaj 作为一个缩写就没有这么容易记住了。

    下面是控制器的 add_to_cart 方法,它会获得一个指定的产品,并将其添加到当前会话的购物车中。这个方法返回购物车对象,以及购物车中商品的总价和商品总数:

 


清单 21. add_to_cart 控制器方法


@expose()

def add_to_cart(self, productID):

    cart = self.get_cart()

    product = Product.get(productID)

    cart.add_product(product, 1)

    return self.results(cart=cart,

        price=cart.total_price,

        quantity=cart.total_quantity)

      


    注意 expose 方法没有提供一个模板名。这是因为这个方法不会从浏览器中直接调用,并在 HTML 中进行呈现。如果我们在浏览器或 curl 之类的工具中直接查看 add_to_cart 页面(http://localhost:8080/add_to_cart/1),就会看到原始的 JSON 数据: {"tg_flash":null, "price":24, "cart":{"id":24}, "quantity":1}

    客户机(浏览器)对服务器上 add_to_cart 控件方法的 JavaScript 调用非常简单。MochiKit 提供了一个名为 loadJSONDoc 的函数,它接收一个 URL,并返回一个称为 deferred 的对象。我们可以使用这个 deferred 对象来定义一个在异步调用返回响应时执行的回调函数。


清单 22. 购物车 AJAX 逻辑(cart.js)

function addToCart(productID) {

 var deferred = loadJSONDoc('/add_to_cart/' + productID);

 deferred.addCallback(updateCart);

}

function updateCart(results) {

 $("cart-amt").innerHTML = numberFormatter("#.00")(results["price"]);

 $("cart-qty").innerHTML = results["quantity"];

}

      

  updateCart 函数是在返回之前调用的,JSON 值是在一个称为 results 的联合数组变量中提供的。这个函数使用 ID 和 innerHTML 属性来更新购物车中商品的数量。此外,MochiKit numberFormatter 函数用来指定价格的小数部分。

     最后一个步骤是添加一个调用上面的 addToCart 函数的链接,这会传递当前的产品 ID。我们还需要将 MochiKit.js 和 cart.js 文件作为脚本标记添加到产品模板中:


清单 23. 将所添加的购物车 JavaScript 调用添加到产品页面中(product.kid)

<head>

    ...

    <script src="/tg_js/MochiKit.js" type="text/javascript" />

    <script src="/static/javascript/cart.js" type="text/javascript" />

</head>

<body>

    ...

    <table>

 ...

  <tr>

   <td colspan="2" align="right">

  <a href="#" onclick="addToCart(${product.id})">Add To Cart</a>

   </td>

  </tr>

 </table>

</body>

      

 

结束语:TurboGears 和 Django 的比较

     Django 和 TurboGears 都是 MVC 风格的框架,开发人员可以利用这些技术使用 Python 语言快速开发 Web 站点。为了选择最适合您的需求的技术,请考虑以下区别:

  • 背景

    这两个项目与 Ruby on Rails 一样,都是从现有的应用程序中提取出来发布到开源社区中的。Django 的历史比较长,来源于一个每天服务于数百万次页面查看请求的在线报纸服务。TurboGears 是从一个胖客户机 —— RSS News Reader 应用程序,目前仍在开发中 —— 中提取出来的。TurboGears 的社区驱动力比 Django 更好,因为它是在现有开源组件上建立起来的。

    这两个项目之间背景的差异导致了不同的项目优先级。Django 项目来源于迅速变化的在线出版业,它重点关注的是一个可以快速构建并修改基于内容的应用程序的框架。TurboGears 项目的基础是消费产品,重点关注的是胖客户机应用程序和可插入体系架构。

  • URLs

    TurboGears 的请求分发机制通过控制器类和方法名进行路由。在添加新控制器类或方法之后,它们就自动变为可用的了。如果我们需要修改执行给定控制器的路径,就需要对代码结构重新进行配置。反之,Django 使用了一个单独的基于正则表达式的配置文件将 URL 映射为底层代码,这样就降低了 URL 路径结构与实际实现之间的耦合程度。

    TurboGears 系统的设置比 Django 更加快捷,因为它只需要一个 expose 操作让新页面变成可用即可。然而,Django 配置系统可以进行最大限度的控制和灵活性。在发生重大变化之后,Django URL 可以简单地重新映射到应用程序上。这个帮助防止由于旧书签或缓存搜索引擎结果引起的 “链接失效” 的情况。“链接失效” 会对 Django 设计用来创建的基于内容的 Web 站点的通信级和可用性造成很大的影响。

  • 代码重用

    TurboGears 团队将他们的项目称为大框架,这样清晰地表达了 TG 是一个由现有的很多组件构成的项目这一思想。TurboGears 团队选择并集成了最好的开源代码,而不是从头重新开始编写。TurboGears 框架的另一个优势是这是一个由很多社区构成的大项目。TG 现在功能已经非常强大,正在强力促进大家对构成 TurboGears 核心组件的兴趣和参与。这样可以起到水涨船高的效果。

    另外一方面,Django 是在 2003 年创建的,当时 Python 组件的状态还不像现在一样稳定。Django Web 栈是从头开始创建的,最终的结果是获得了一个稳定的框架,这个框架已经被用来创建了多个每天处理数百万点击率的 Web 站点。然而,有些人评论说 Django 项目可能会由于缺乏代码的重用而遭遇 NIH(Not Invented Here)问题。Django 团队的立场是在 Python 中从头创建一个框架所需要的工作不会比将现有的组件拼装在一起更困难,这样最终可以生成一个更统一的框架。

  • JavaScript

    TurboGears 在自己的框架中首先提供了 MochiKit,这是一个 JavaScript 库。这个团队还创建了一个部件库,它可以充分利用 JavaScript 创建丰富的表单元素。这显示了胖客户机(Ajax)开发在 TurboGears 世界中是多么重要。Django 团队没有选择使用一个 JavaScript 库来默认地包含自己的框架,但是他们已经对这种可能性展开了讨论。这两个项目都不会限制我们使用任何 JavaScript 库。

  • 管理工具

    这两个项目都有管理接口。Django 管理工具的目标用户是那些需要良好数据入口工具的终端用户,这样每次向应用程序中添加新功能时就不需要对工具进行定制了。另一方面,TurboGears 管理工具重点关注的是开发人员的需要:它为开发人员提供了一组设计工具,以及一个基本的数据库查看器和编辑器。

  • 许可证

    由于 Django 是从头开始创建的,因此整个项目都使用的是开源许可证(BSD 许可证)。TurboGears 是由多个项目构成的,使用了多个许可证。SQLObject(ORM 工具)是使用 LGPL(Lesser General Public License)保护的,这说明对 SQLObject 进行的任何直接修改都需要贡献回这个项目。这个许可证并 要求使用它的应用程序也开放源代码。不过有些公司会禁止使用受 LGPL 许可证保护的软件。在这种情况下,我们可以考虑使用 SQLAlchemy,它是 TG 社区大力支持的另外一个 ORM 工具。

  • 实际例子

    请参见 参考资料 部分给出的已知的 Django 和 TurboGears 驱动的站点的列表。这些实际的应用程序展示了我们可以使用每个工具实现什么功能。

关于作者

作者照片:Ian Maurer

Ian Maurer 是 Brulant, Inc. 的一名资深顾问,他擅长使用开源软件和 IBM WebSphere 技术为各个行业开发集成的电子商务解决方案,其中包括消费品和零售行业。Ian 居住在东北部的俄亥俄州,他是 Cleveland Area Python Interest Group 的成员。

  • 上一篇Linux:

  • 下一篇Linux:
  • 最 新 热 门
     VMware下Linux与真实主机共享上网
     Linux系统安全隐患及加强安全管理方法
     各类Unix和Linux密码丢失解决方法
     配置Linux操作系统的环境变量
     在Linux系统下刷新主板BIOS的好方法
     删除文件提示:Operation not permitted
     Linux系统下硬盘挂载详细说明
     Linux文本模式下如何发送带附件的Email
     在Linux自动生成一个保险密码的方法
     Linux商业电影动画制作软件列表
    最 新 推 荐
     Python anygui 项目预览
     Python 之优雅与瑕疵
     python 中文解决方法 gb2312 <==> utf8
     Python anygui 项目预览
     使用TurboGears和Python开发Web 站点
     Python编程技巧-使用状态机
     Curses 编程 -- 给初学者的提示
     概说Python编程
     无所不能的python
     简明 Python 教程
    相 关 文 章

    Ubuntu Linux系统下TP-link无线上网方法
    Ubuntu Linux系统中如何使用Samba客户端
    Kubuntu 8.04 系统确认用KDE4取代LTS
    Linux Shell脚本Ldd命令原理使用方法
    Ubuntu 7.10 Linux建立C与GTK的开发环境
    Ubuntu中Vsftp的配置和使用
    在Ubuntu Linux中配置虚拟主机
    Ubuntu系统下Trac+Subversion+Apache安装
    使用Smartmontools工具来检测硬盘的状态
    Ubuntu Linux系统配置SSH验证

    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 网站公告

     

    Copyright 2006-2008 pcjx.com All Rights Reserved
    电脑技巧 版权所有 粤ICP备06059145号 地图
    本网站所有内容未经许可不得转载或做其他使用