1. 数据库配置

  • Django默认支持sqlite, mysql, oracle, postgresql 数据库:

    • Django默认使用sqlite数据库,引擎名称:django.db.backends.sqlite3
    • MySQL 引擎名称:django.db.backends.mysql
  • MySQL 驱动程序:
    • MySQLdb(mysql python)
    • mysqlclient
    • MySQL
    • PyMySQL(纯python的mysql驱动程序)
# 示例: 更改数据库
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'books', # 数据库名称
'USER': 'root', # 数据库用户名
'PASSWORD': 'root', # 数据库密码
'HOST': '', # 数据库主机,留空默认为localhost
'PORT': '3306', # 数据库端口
}
} # 注意:
# 启动项目时,会报错: no module named MySQLdb
# 这是因为django默认导入的驱动是 MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是
# PyMySQL
#解决方法:
# __init__.py 中加入以下代码:
# import pymysql
# pymysql.install_as_MySQLdb()

2. ORM(对象关系映射)

  • 表的创建:

    • 作者模型: 一个作者有姓名;
    • 作者详细模型: 把作者的详情放到详情表,包含性别, email地址和出生日期。作者详情模型和作者模型之间

      是一对一的关系(one-to-noe),在大多数情况下,我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。
    • 出版商模型: 出版商有名称,地址,所在城市,省,国家和网站;
    • 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和数据的关系

      就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系

      (one-to-many),也被称作外键。
# 实体类
# 项目名(orm)/app01/models.py
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30, verbose_name='名称')
address = models.CharField('地址', max_length=50)
city = models.CharField('城市', max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField() class Meta:
verbose_name = '出版商'
verbose_name_plural = verbose_name def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=30) def __str__(self):
return self.name class AuthroDetail(models.Model):
sex = models.BooleanField(max_length=1, choices=((0, '男'), (1, '女'),))
email = models.EmailField()
address = models.CharField(max_length=50)
birthday = models.DateField()
author = models.OneToOneField(Author, on_delete=models.CASCADE) class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher, null=True, on_delete=models.SET_NULL)
publication_date = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2, default=10) def __str__(self):
return self.title # 创建表
# iTerm 中进入 项目名(orm) 下
python3 manage.py makemigrations
python3 manage.py migrate # 备注:
# 1. on_delete 属性说明
# CASCADE: 级联删除
# PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出 ProtectedError 错误;
# SET_NULL: 置空模式,删除的时候, 外键自动被设置为空, 前提就是 blank=True, null=True;
# SET_DEFAULT: 删除的时候,外键自动设置为默认值。定义外键的时候,需要加上一个默认值;
# SET(): 自定义一个值,该值当然只能是对应的实体; # 2. 每个数据模型都是 django.db.models.Model 的子类, 它的父类Model包含了所有必要的和数据库交互的方法,
# 并提供了一个简洁漂亮的定义数据库字段的语法;

2.1 模型常用的字段类型参数

# CharField
# 字符串字段,用于较短的字符串
# CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数 # InterField: 用于保存一个整数
# FloatField: 一个浮点数, 必须提供两个参数:
# max_digits: 总位数(不包括小数点和符号)
# decimal_places: 小数点位数
# 例如,要保存最大值为 999(小数点后保存2位)
# models.FloatField(..., max_digits=5, decimal_palces=2) # AutoField
# 一个 IntegerField, 添加记录时,会自动增长,通常不需要直接使用这个字段
# 自定义一个主键: my_id=models.AutoField(primary_key=True)
# 如果不指定主键的话,系统会自动添加一个主键字段到你的 model # BooleanField
# admin 用 checkbox 来表示此类字段 # TextField
# 一个容量很大的文本字段
# admin 用一个 <textarea> 表示该字段数据 # EmailField
# 一个带有检查Email合法性的 CharField, 不接受 maxlength 参数 # DateField
# 一个日期字段, 共有下列额外的可选参数:
# Argument 描述
# auto_now 当对象被保存时,自动将该字段的值设置为当前时间, 通常用于表示"last-modified"时间戳
# auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间 # DateTimeField
# 一个日期时间字段, 类似 DateField 支持同样的附加选项 # FileField
# 一个文件上传字段
# 要求一个必须有的参数, upload_to:用于保存上传文件的本地文件系统路径,这个路径必须包含 strftime
# formatting: 格式化上传文件的 date/time # ImageField
# 类似 FileField, 不过要校验上传对象是否是一个合法图片;
# 两个可选参数: height_field, width_field
# 如果提供这两个参数,则图片将按提供的高度和宽度保存 # 注意: 在 model 中使用 FileField 或 ImageField, 需要以下步骤,
# 1) settings.py 中定义一个完整路径给 MEDIA_ROOT,以便让Django在此处保存上传的文件;
# (出于性能考虑,这些文件并不保存到数据库),定义 MEDIA_URL,作为该目录的公共 URL,要确保该目录对WEB服务器
# 用户帐号是可写的
# 2) 在model添加 FileField 或 ImageField,需要确保定义了 upload_to 选项,以告诉 Django 使用
# MEDIA_ROOT 的哪个子目录保存上传文件,数据库要保存的只是文件的路径(相对于 MEDIA_ROOT)
# 3) 可以使用Django提供的 get_<#fieldname>_url 函数,获取图像的绝对路径:
# 例如,ImageField 叫作 mug_shot, 就可以在模板中 {{ object.#get_mug_shot_url }} 获取图像 # URLField
# 用于保存 URL, 若 veriry_exists 参数为 True(默认), 给定的 URL 会预先检查是否存在(即URL 是否
# 被有效装入且没有返回404) # NullBooleanField
# 类似 BooleanField, 不过,允许NULL作为其中一个选项,推荐使用这个字段,而不要用 BooleanField 加
# null = True 选项
# damin 用一个选择框 <select> (三个选择的值: "Unknow", "Yes" 和 "No") 来表示这种字段数据 # SlugField
# "Slug" 是一个报纸术语, slug 是某个东西的小小标记(短签),只包含字母,数字,下划线和连字符;
# 它们通常用于 URLs;
# maxlength 默认值为 50 # XMLField
# 校验值是否为合法XML的 TextField,
# 必须提供参数: schema_path
# 它是一个用来校验文本的 RelaxNGschema 的文件系统路径 # FilePathField
# 某个特定目录下的文件名,支持三个特殊的参数,其中第一个是必须提供的.
# path: 必需参数,一个目录的绝对文件系统路径.
# match: 可选参数, 一个正则表达式,作为一个字符串, FilePathField 将使用它过滤文件名.
# 这个正则表达式只会应用到 base filename 而不是路径全名
# recursive 可选参数, 要么True,要么False, 默认值是 False. 是否包括 path 下面的全部子目录. # IPAddressField
# 一个字符串形式的 IP 地址, 例如 '127.0.0.1' # CommaSeparatedIntegerField
# 用于存放逗号分隔的整数值, 必须要有 maxlength 参数;

2.2 Field 重要参数

null: 数据库中字段是否可以是空

blank: django 的 Admin 中添加数据时,是否允许空值

default: 设定缺省值

editable: 如果为假, admin 模式下将不能改写, 缺省为真;

primary_key: 设置主键, 如果没有设置,Django 创建表时,会自动加上;

unique: 数据唯一;

verbose_name: Admin 中字段的显示名称;

validator_list: 有效性检查, 非有效产生 django.core.validators.ValidationError 错误

db_column, db_index: 如果为真,将为此字段创建索引

choices: 一个用来选择值的二维数组,第一个值是实际存储的值, 第二个用来备选;

3. 表的操作

3.1 增(create, save)

from app01.models import *

    # create 方式一: Author.objects.create(name='Jame')

    # create 方式二: Author.objects.create(**{'name':'Jame'})
# 以字典的方式插入,前面需要添加两个星号 # save 方式一:
author = Author(name='Jame')
author.save() # save 方式二:
author=Author()
author.name='Jame'
author.save() # 如何处理外键关系的字段,如一对多的publisher和多对多的authors # 一对多(ForeignKey):
# 方式一: 由于绑定一对多的字段,例如publisher,存到数据库中的字段为 publisher_id,
# 所以我们可以直接给这个字段设定对应值:
Book.objects.create(title='Python 入门',
publisher_id=2,
publication_date='2015-4-18',
price=98) # 方式二:
# 首先,获取绑定的 Publisher对象
pub_obj = Publisher(name='河北教育出版社',address='保定',city='保定',
state_province='河北',country='China',website='http://www.edu.com')

pub_obj=Publisher.objects.get(id=1) # 将 publisher_id=2 改为 publisher=pub_obj # 多对多(ManyToManyField): author1 = models.Author.objects.get(id=1)
author2 = models.Author.objects.filter(name='zhangsan')[0]
book = models.Book.objects.get(id=1)
book.author.add(author1, author2) # book.author 表示book绑定的 author 对象集合 # 等同于
----------- 正向查询(从拥有外键的表开始查找)
book.author.add(*[author1, author2])
book.author.remove(*[author1, author2]) ----------- 反向查询
book=models.Book.objects.filter(id__gt=1) # id__gt 表示 id大于
authors=models.Author.objects.filter(id=1)[0]
authors.book_set.add(*book) # Author 类里面没有与 book 相关的属性
authors.book_set.remove(*book) # 注意: 如果第三张表是通过 models.ManyToManyField() 自动创建的, 那么绑定关系只有上面一种方式
# 如果第三张表是自己创建的:
class Book2Author(models.Model):
author = models.ForeignKey("Author")
book = models.ForeignKey("Book") # 绑定联合唯一索引
class Meta:
unique_together=["author", "book"] # 保存数据
s = models.Book2Author.objects.create(author_id = 1, Book_id = 2)
s.save()

3.2 删除(delete)

# 单表:
Book.objects.filter(id=1).delete() # 备注: 表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在 Book_authors 表中有两条
# 相关信息,这种删除方式就是 django 默认的级联删除。 # 多对多关系: remove() 和 clear() 方法
# 正向
book = models.Book.objects.filter(id=1) # 删除第三张表中和id=1关联的所有关联信息
book.author.clear() # 清除与book中 id=1 关联的所有数据
book.author.remove(*[1, 2, 3, 4]) # 反向
author = models.Author.objects.filter(id=1)
author.book_set.clear() # 清除与book中 id=1 关联的所有数据

3.3 修改(update 和 save)

# 单表:
# 方式一: update 方法直接设定对应属性
Book.objects.filter(id=2).update(title='Python') # 不能用 get(id=2) # SQL
# UPDATE 'app01_book' SET 'title' = 'Python' WHERE 'app01_book'.'id'=2; args=('Python', 2) # 不能用get的原因是: update 是 QuerySet对象的方法, get返回的是一个model对象,它没有 update 方法,
# 而 filter 返回的是一个 QuerySet 对象; # 方式二: save 方法会将所有属性重新设定一遍, 效率低
obj=models.Book.objects.filter(id=2)[0]
obj.title='Python'
obj.save() # SQL:
# SELECT 'app01_book'.'id','app01_book'.'title','app01_book'.'price','app01_book'.'color',
# 'app01_book'.'page_num','app01_book'.'publisher_id' FROM 'app01_book'
# WHERE 'app01_book'.'id'=3 LIMIT 1; # UPDATE 'app01_book' SET 'title'='Python','price'=22,'color'='red','page_num'=223,
# 'publisher_id'=1 WHERE 'app01_book'.'id'=3;

3.3.1 控制台输出SQL语句

# setting 加上日志记录部分
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}
}

3.4 查询(filter, valued等)

  1. 查询相关API:

    • filter(**kwargs): 包含了与所给筛选条件相匹配的对象;
    • all(): 查询所有结果;
    • get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的

      对象超过一个或者没有都会抛出错误。
  2. 对查询的结果进行再处理(例如,objects.filter.values())
    • values(*field): 返回一个ValueQuerySet,一个特殊的QuerySet,运行后得到的并不是一系列

      model的实例化对象,而是一个可迭代的字典序列;
    • exclude(**kwargs): 包含了与所给筛选条件不匹配的对象;
    • order_by(*field): 对查询结果排序;
    • reverse(): 对查询结果反向排序;
    • distinct(): 从返回结果中剔除重复记录;
    • values_list(*field): 返回一个元组序列;
    • count(): 返回数据库中匹配查询(QuerySet)的对象数量;
    • first(): 返回第一条记录;
    • last(): 返回最后一条记录;
    • exists(): 如果QuerySet包含数据,就返回 True, 否则返回 False。
# 补充:
# 扩展查询,有时候Django的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
# extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 1) q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-12-29'"})
q = q.extra(order_by=['-is_recent']) # 负号表示逆序 2) Blog.objects.extra(
select = SortedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two')) 3) Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

3.4.1 QuerySet

  1. 惰性机制: Publisher.objects.all()或者.filter()等都只是返回一个QuerySet(查询结果集对象),

    它并不会马上执行SQL, 而是当调用QuerySet的时候才执行。
  2. QuerySet的特点:
    • 可迭代的
    • 可切片
# 示例:
objs = models.Book.objects.all() #[obj1, obj2, obj3...] # 可迭代
for obj in objs: # 每一个obj,就是一个行对象
print('obj:',obj) # 可切片
print(objs[1])
print(objs[1:4])
print(objs[::-1]) # QuerySet 是具有cache的
# 当遍历QuerySet时,所有匹配的记录会从数据库获取,然后转换成Django的model,这被称为执行(evaluation)
# 这些model会保存在QuerySet内置的cache中,如果再次遍历这个QuerySet,不需要再去数据库查询
objs=models.Book.Objects.filter(id=3) for i in objs:
prin(i) # SQL 语句只运行一次 for i in objs:
print(i) # 当QuerySet非常巨大时,cache会成为问题
# 处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的QuerySet可能会锁住系统
# 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生QuerySet cache, 可以使用 iterator()
# 方法来获取数据,处理完数据就将其丢弃
objs=Book.objects.all().iterator() # 迭代器对象 for obj in objs:
print(obj.name) # 当然,使用iterator()方法来防止生成cache, 意味着遍历同一个QuerySet时,会重复执行查询。所以使用
# iterator()的时候要当心,确保代码在操作一个大的QuerySet时,没有重复执行查询。

3.4.2 单表条件查询 多表条件关联查询

# 示例:了不起的双下划线(__)之单表条件查询

models.Tb1.objects.filter(id__lt=10, id__gt=1)      # 获取id大于1, 且小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])      # 获取id等于11, 22, 33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains 表示大小写不敏感 models.Tb1.objects.filter(id__range=[1, 2]) # 范围 between and startswith, istartswith, endswith, iendswith # 示例: 多表条件关联查询 # 正向条件查询
models.Book.objects.filter(title="Python").values("id") # 一对多
models.Book.objects.filter(title="Python").values("publisher__city") # 多对多
models.Book.objects.filter(title="Python").values("author__name")
models.Book.objects.filter(author__name="zhangsan").values("title")

3.4.3 聚合查询和分组查询

# aggregate(*args, **kwargs):

from django.db.models import Avg, Min, Sum, Max

# 查询图书价格的平均值
Book.objects.all().aggregate(Avg('price')) # {'price__avg': 20} # 查询图书价格的最大值,最小值
Book.objects.all().aggregate(Avg('price'), Max('price'), Min('price')) # 输出: {'price__avg': 20, 'price__max':Decimal('81.20'), 'price__min': Decimal('12.99')} # aggregate() 是 QuerySet 的一个终止子句,意思是说, 它返回一个包含一些键值对的字典。键的名称是聚合值
# 的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
# 一个名称,可以向聚合子句提供
Book.objects.all().aggregate(average_price=Avg('price')) # annotate(*args, **kwargs) 分组查询
# 查询各个作者出的书的总价格,这里就涉及到分组了, 分组条件是 authors__name
Book.objects.values("authors__name").annotte(Sum("price")) # 查询各个出版社最便宜的书价是多少
Book.objects.values("publisher__name").annotate(Min("price"))

3.4.4 F 查询和 Q 查询

# 示例一: F 查询
# F 使用查询条件的值,专门取对象中某列值的操作, 例如,将书的价格增加 10
from django.db.models import F
models.Book.objects.update(price=F('price')+10) # 示例二: Q 构建搜索条件
from django.db.models import Q # Q 对象可以对关键字参数进行封装,从而更好地应用多个查询
models.Book.objects.filter(Q(title__startswith='P')).all() # 可以组合使用 &, | 操作符,当一个操作符用于两个Q的对象,它产生一个新的Q对象
Q(title__startswith='P') | Q(title__startswith='J') # Q 对象可以用 ~ 操作符放在前面表示否定, 也可允许否定与肯定形式的组合
Q(title__startswith='P') | ~Q(pub_update__year=2005) models.Book.objects.get(
Q(title__startswith='P'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 10, 1))
) # Q对象可以与关键字参数查询一起使用,不过,一定要把Q对象放在关键字参数查询的前面:
# 正确:
models.Book.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 10, 1)),
title__startswith='P') # 错误:
models.Book.objects.get(
title__startswith='P',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 10, 1))
)

4. admin 的配置

  • admin 是 Django 强大功能之一,它能从数据库中读取数据,呈现在页面上,进行管理。
  • 注册model类到admin的两种方式:
    • 使用register方法:admin.site.register(Book, MyAdmin)
    • 使用register的装饰器:@admin.register(Book)
# 示例:
# 一些常用的设置:
# list_display: 指定要显示的字段
# search_fields: 指定搜索的字段
# list_filter: 指定列表过滤器
# ordering: 指定排序字段 from django.contrib import admin
from app01.models import * # 注册model
class MyAdmin(admin.ModelAdmin):
list_display = ("title", "price", "publisher")
search_fields = ("title", "publisher")
list_filter = ("publisher",)
ordering = ("price",)
fieldsets = [
(None, {'fields': ['title']}),
('price information', {'fields': ['price', 'publisher'], 'classes': ['collapse']}),
] admin.site.register(Book, Admin)
admin.site.register(Publish)
admin.site.register(Author)

参考资料:

Django 框架之 Models的更多相关文章

  1. django框架的models

    在django的框架设计中采用了mtv模型,即Model,template,viewer Model相对于传统的三层或者mvc框架来说就相当对数据处理层,它主要负责与数据的交互,在使用django框架 ...

  2. Django框架之models和不依赖Qquery的ajax请求

    一.models表字段 1)class表字段的创建 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) ...

  3. django框架<二>

    django框架:   Models 1.基本创建 Django提供了一个抽象层("Model")的构建和管理Web应用程序的数据. Django使用一种新的方式,即:关系对象映射 ...

  4. 第三百零九节,Django框架,models.py模块,数据库操作——F和Q()运算符:|或者、&并且——queryset对象序列化

    第三百零九节,Django框架,models.py模块,数据库操作——F()和Q()运算符:|或者.&并且 F()可以将数据库里的数字类型的数据,转换为可以数字类型 首先要导入 from dj ...

  5. 第三百零八节,Django框架,models.py模块,数据库操作——链表结构,一对多、一对一、多对多

    第三百零八节,Django框架,models.py模块,数据库操作——链表结构,一对多.一对一.多对多 链表操作 链表,就是一张表的外键字段,连接另外一张表的主键字段 一对多 models.Forei ...

  6. 第三百零七节,Django框架,models.py模块,数据库操作——表类容的增删改查

    Django框架,models.py模块,数据库操作——表类容的增删改查 增加数据 create()方法,增加数据 save()方法,写入数据 第一种方式 表类名称(字段=值) 需要save()方法, ...

  7. 第三百零六节,Django框架,models.py模块,数据库操作——创建表、数据类型、索引、admin后台,补充Django目录说明以及全局配置文件配置

    Django框架,models.py模块,数据库操作——创建表.数据类型.索引.admin后台,补充Django目录说明以及全局配置文件配置 数据库配置 django默认支持sqlite,mysql, ...

  8. 五 Django框架,models.py模块,数据库操作——表类容的增删改查

    Django框架,models.py模块,数据库操作——表类容的增删改查 增加数据 create()方法,增加数据 save()方法,写入数据 第一种方式 表类名称(字段=值) 需要save()方法, ...

  9. 四 Django框架,models.py模块,数据库操作——创建表、数据类型、索引、admin后台,补充Django目录说明以及全局配置文件配置

    Django框架,models.py模块,数据库操作——创建表.数据类型.索引.admin后台,补充Django目录说明以及全局配置文件配置 数据库配置 django默认支持sqlite,mysql, ...

随机推荐

  1. SAP ECC6安装系列五:安装后 License 的处理

    原作者博客 http://www.cnblogs.com/Michael_z/ ======================================== 我发现我确实比较懒,先和各位说声抱歉了 ...

  2. jdom 读取

    读取XML文档 读取文档,首先需要一个xml的解析器,它可以自动的解析出各个元素,并且把子元素作为自己的孩子节点,方便操作. 主要使用的函数: SAXBuilder.build("xxx.x ...

  3. dbcp 详细配置

    1.配置参数 username : 连接用户名 password:  连接密码 url :  连接 url( 如果连接 mysql ,格式为 jdbc:mysql://ip:port/dbname) ...

  4. dp背包之01背包poj2184

    http://poj.org/problem?id=2184 题意:给定两个属性,求这两个属性的和的最大值......... 思路:将第一个属性往后平移1000个单位,然后推导其动态转移方程,若是dp ...

  5. WebService或HTTP服务端接收请求转发消息到另一个服务端-实现思路

    1.需求结构(WebService) A客户端<->B服务端<->C服务端 说明: a.在B服务端上面添加配置项(1.是否转发消息到C服务端:2.C服务端IP和端口): b.A ...

  6. go hmac使用

    https://github.com/danharper/hmac-examples 94 func generateSign(data, key []byte) string { 95 mac := ...

  7. 数学 - Codeforces Round #319 (Div. 1)A. Vasya and Petya's Game

    Vasya and Petya's Game Problem's Link Mean: 给定一个n,系统随机选定了一个数x,(1<=x<=n). 你可以询问系统x是否能被y整除,系统会回答 ...

  8. openresty 视频

    http://v.163.com/paike/V8H1BIE6U/V949ER8RD.html#from=search

  9. 如果想要跨平台,在file类下有separtor(),返回锁出平台的文件分隔符

    对于命令:File f2=new file(“d:\\abc\\789\\1.txt”) 这个命令不具备跨平台性,因为不同的OS的文件系统很不相同. 如果想要跨平台,在file类下有separtor( ...

  10. 《网络编程》非堵塞 I/O

    概述 在前面文章中,我们介绍了 I/O 的五种模型<I/O 模型>.从那里能够知道,非堵塞式的 I/O 是进程调用 I/O 操作时.若数据未准备就绪.则马上返回一个 EWOULDBLOCK ...