写代码要尽可能的捕获异常



模板的路径可以直接放到TEMPLATES里面的DIRS当中,TEMPLATE_DIRS可以取消掉
设置static静态文件STATICFILES_DIRS里面,这是一个元组
> virtualenv env
# 之后会自动创建一个 env 文件夹
    # 下面,有: Include,Lib,Scripts 三个文件夹
 
# 若要进入隔离环境
env\Scripts\activate 
(env) > 
# 此时便进入了隔离环境

virtualenv安装到了python2.7里面的site-package里面了site-packages里面放的是第三方包。


然后设置静态文件和模板,
url还可以这样写,是什么意思?这么写的意思是访问localhost:8000然后访问index,这个index是从blog.views里面导入的,另一种方式就是
直接手写index的路径,写成blog.views.index都是一样的

{% static  '.js' %}这样写会被翻译成/static/.js

使用日志器

在settings.py里进行设置,对其中文件路径进行修改
里面的路径如果不存在会在输出错误日志时创建
日志器有不同级别
在views.py里引入日志器,通过import logging
logger = loggin.getLogger('blog.views')

通过错误日志,可以很好的把帮助我们分析为什么出错?

可以把信息保存在settings.py里面,也可以保存在数据表当中
设置在settings里面等于是相当于设置全局变量
在views.py当中引用
先import django.conf import settings
通过这种方式引用:site_name = settings.SITE_NAME
不过这种方式引用太麻烦
可以直接定义一个函数,将settings内容读取出来,进行输出
  1. def global_setting():
  2. return{'SITE_NAME':settings.SITE_NAME,
  3. 'SITE_DESC':settings.SITE_DESC,
  4. }
把这个方法加到settings.py里面的TEMPLATES的OPTIONS的上下文处理器这个配置
在这个处理器执行的时候,每个页面都可以用到,
  1. 'blog.views.global_setting',
于是我可以直接在模板当中调用global里面的变量,字典的名字
如html当中
  1. SITE_NAME


models设计:
当定义__unicode__的时候,return返回的为字符串
用户模型,可以直接从Django里面继承,也可以采用关联的方式
用户模型:
第一种:采用的继承方式扩展用户信息(本系统采用)需要在settings里面进行设置
第二种:扩展,关联的方式去扩展用户信息
什么意思?模型从Django里面继承,为什么不自己写了然后继承?
采用继承的方式扩展用户信息,帮我们封装了一些用户分组和权限机制在里面
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
在setttings里面声明AUTH_USER_MODEL = 'blog.User'
关联表又是什么东西?    
两个表有联系,这个联系先理解为外键,这两个表就可以叫做关联表,可以是多对一,多对多,一对一
migration又是什么?

1. 新的命令

Django 1.7 为我们带来了三个新命令:

  • migrate: 用于执行迁移动作

  • makemigrations: 基于当前的model创建新的迁移策略文件

  • sqlmigrate: 显示迁移的SQL语句

值得注意的是, migration是基于App的, 因此, 我们可以针对某些app不启用migration功能.

2. 如何使用

migrations的使用非常简单: 修改model, 比如增加field, 然后运行

    python manager.py makemigrations

你的mmodel会被扫描, 然后与之前的版本作比较, 在app的migrations目录下生成本次迁移文件.

我们建议查看一下该迁移文件, 确保没有问题. 然后运行:

    python manager.py migrate

migrate命令会进行比较, 并应用该迁移.

django.contirb标准库是什么?

Django标准库

Django的标准库存放在 django.contrib 包中。每个子包都是一个独立的附加功能包。 这些子包一般是互相独立的,不过有些django.contrib子包需要依赖其他子包。

在 django.contrib 中对函数的类型并没有强制要求 。其中一些包中带有模型(因此需要你在数据库中安装对应的数据表),但其它一些由独立的中间件及模板标签组成。

django.contrib 开发包共有的特性是: 就算你将整个django.contrib开发包删除,你依然可以使用 Django 的基础功能而不会遇到任何问题。 当 Django 开发者向框架增加新功能的时,他们会严格根据这一原则来决定是否把新功能放入django.contrib中。


需要安装的库Django MySQL-python pip setuptoolls virtualenv wheel
pillow
安装库的过程mysqldb安装不上:

pycharm虚拟环境virtualnv安装MySQL扩展http://my.oschina.net/NoSay/blog/474567

这里有教程

easy_install MySQL-python这个可以用,大声说一声NB

关于Django Models的设计和使用,关于在Django中配置mysql数据库,以及如何生成数据库。

# -*- coding:utf-8 -*-
from django.db import models
from django.contrib.auth.models import AbstractUser


# 用户模型.
class User(AbstractUser):
    avatar = models.ImageField(upload_to='avatar/%Y/%m', default='avatar/default.png', max_length=200, blank=True, null=True, verbose_name='用户头像')
    qq = models.CharField(max_length=20, blank=True, null=True, verbose_name='QQ号码')
    mobile = models.CharField(max_length=11, blank=True, null=True, unique=True, verbose_name='手机号码')

    class Meta:
        verbose_name = '用户'
        verbose_name_plural = verbose_name
        ordering = ['-id']

    def __unicode__(self):
        return self.username

还需要在settings里面进行设置,#自定义用户model
AUTH_USER_MODEL = 'blog.User'
avatar = models.ImageField(upload_to='avatar/%Y/%m', default='avatar/default.png', max_length=200, blank=True, null=True, verbose_name='用户头像')
ImageField是图像字段 upload_to是上传路径 default默认图片
需要在settings里面设置上传路径

配置admin
装Django1.9时,创建的superuser账号和密码不能相同,卧槽,1.9版本的密码要求很规范

    from models import *   admin.site.register(User)  在admin当中进行设置
models如果不加修改,以默认选择设置admin,还可以自定义models
在admin里面进行自定义
class ArticleAdmin(admin.ModelAdmin):
fields = ('title','desc','content')

admin.site.register(Article,ArticleAdmin)
如果不加后面的ArticleAdmin,就默认的形式进行设定
fields 显示指定字段  exclude 出了指定字段,显示其他字段
fieldsets可以对要设定的字段做一个很好的划分,把一部分隐藏,一部分显示
list_display可以显示指定的列
list_display_links指定列可以点击
还有很多属性,需要用的时候查阅官方文档

富文本编辑器
可以不仅仅插入文字,还可以插入图片,视频等
django-admin中添加富文本编辑器的几种方式:
1、使用第三方的一些库,如django-ckeditor
(https://pypi.python.org/pypi/django-ckeditor)
2、在admin中定义富文本编辑器的widget
3、通过定义ModelAdmin的媒体文件

步骤:
1、下载kindeditor
复制到static的js目录下
2、定义ModelAdmin的媒体文件
这个是在admin当中进行配置的
class ArticleAdmin(admin.ModelAdmin):
exclude = ('title','desc','content')
class Media:
js = (
'/static/js/kindeditor-4.1.10/kindeditor-min.js',
'/static/js/kindeditor-4.1.10/lang/zh_CN.js',
'/static/js/kindeditor-4.1.10/config.js',
        )3、修改kindeditor的配置文件
也就是在config.js文件中新建一个对象
asp asp.net examples jsp php 这些文件可以删除
在KinderEditor的官方文档照到相应的配置
然后再config.js当中进行配置
  1. KindEditor.ready(function(K) {
  2. K.create('textarea[name=content]',{
  3. width:800,
  4. height:200,
  5. });
  6. });
Pillow是python的一个图像处理库,django-ckeditor需要依赖该库。最简单的安装方法,当然是使用pip,假设你装过pip,可以直接运行以下命令安装:



上传文件
KinderEditor没有提供python的上传文件的接口,所以需要自己进行配置
固定上传的目录为uploads
url(r"^uploads/(?P<path>.*)$", \
"django.views.static.serve", \
{"document_root": settings.MEDIA_ROOT,}),

uploads 是说明这是一个路由的地址,(?P<path>.*)$"这里可以是任意字符, "django.views.static.serve"是调用django里面的server方法
"
document_root": settings.MEDIA_ROOT,这是对应路径
avatar = models.ImageField(upload_to='avatar/%Y/%m', default='avatar/default.png', max_length=200, blank=True, null=True, verbose_name='用户头像')
upload_to='avatar/%Y/%m'自定义上传路径,上传到指定文件


步骤:
在settings.py文件里面进行设置
MEDIA_URL = '/uploads/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
创建uploads文件夹
在url文件当中引入settings  from django.conf import settings

url(r"^uploads/(?P<path>.*)$", \ "django.views.static.serve", \ {"document_root": settings.MEDIA_ROOT,}),

avatar = models.ImageField(upload_to='avatar/%Y/%m',在models里面已经设置了上传路径,是在settings里面设置的路径下面,这里写的是avatar/年/月 存储
http://localhost:8000/uploads/avatar/2015/12/mamao.jpg 因为在url里面有设置,所以可以直接在输入url也可以访问到

富文本编辑器上传文件:
在blog下面新建一个models.py文件,直接找写好的代码
kindeditor图片上传返回数据格式说明:
# {"error": 1, "message": "出错信息"}
# {"error": 0, "url": "图片地址"}
配置url
from blog.upload im @csrf_exempt  这个装饰器的作用是 不再做远程表单提交验证
port upload_image
url(r'^admin/upload/(?P<dir_name>[^/]+)$', upload_image, name='upload_image'),  
upload_image是upload.py里面的方法   
dir_name 是和upload_image里面的传入参数相对应的

在KendEditor设置上传路径,也就是先前设置富文本编辑器创建的config.js文件
uploadJson: '/admin/upload/kindeditor',  这个路径是先前在url已经定义好的,这里定义了在uplaod文件夹下面的kindeditor文件夹dir_name = dir_name + '/%d/%d/' %(today.year,today.month)在uploads.py里面已经进行了定义了在kindeditor目录下的路径



基本查询

导入models在views.py里面,
在index里面进行设置,category_list = Category.objects.all()[:1]导入分类信息,
return render(request,'index.html',{'category_list':category_list})将信息传入到category_list当中
QuerySet[:1]这是只取出头一条信息,只是从数据库取出一条信息,而不是取出所有信息然后进行截取
直接在base.html当中进行引用
{% for category in category_list %}
    <a href="base.html" target="_blank">{{category.name}}</a>
{% endfor %}
怎么理解QuerySet的查询是惰性的(当我们去执行all,filter,get,是不会去执行sql的,
当我们去调用查询结果集的时候会执行sql)

{% for category in category_list %}
<a href="base.html" target="_blank">{{category.name}}</a>
{% endfor %}
改为 <a href="base.html" target="_blank">{{category.name}}</a>
这样不会执行sql语句,虽然views.py里面的index方法中定义了查询语句
category_liset = Category.objects.all()
这样做的话是不会执行sql语句的
如果在后面加上
for c in category_list:
    print(c)
这样就会执行sql语句

小技巧:type(category_list) 返回的是QuerySet   type('sss')返回str
先写注释,再写代码思路会更加清晰
以models当中的数据表为对象,在html里面进行操作,在views里面进行逻辑操作,传递参数给html,
在views里面先导入相关的模块
from django.core.paginator import Paginator,InvalidPage,EmptyPage,PageNotAnInteger
article_list = Article.objects.all()
paginator = Paginator(article_list,2)
try:
page = int(request.GET.get('page',1))
article_list = paginator.page(page)
except (EmptyPage,InvalidPage,PageNotAnInteger):
article_list = paginator.page(1)

<p class="autor"><span class="lm f_l"><a href="/">
{% for tag in article.tag.all %}{{ tag.name }}</a></span>{% endfor %}
<span class="dtime f_l">{{ article.date_publish |date:'Y-m-d' }}</span>
<span class="viewnum f_r">浏览(<a href="/">{{ article.click_count }}</a>)
</span><span class="pingl f_r">评论(<a href="/">{{ article.comment_set.all.count }}</a>)
</span></p>
{{ article.comment_set.all.count }}这么写的原因 是comment做为子表,是ForeignKey关联,内置有count方法,可以直接调用
{% for tag in article.tag.all %} tag是表,是一个多对多的关系

去重复方法:distinct是Django自带的去重复方法,对整个字段进行去重
3、django中直接使用sql的两种方式
SELECT DISTINCT DATE_FORMAT(date_publish, '%Y-%m') as col_date FROM blog_article ORDER BY date_publish
3.1、raw (异常:Raw query must include the primary key,返回结果必须包含主键)
3.2、excute
可以直接在Django中写sql语句进行查询,但不推荐这种方式
如 Article.objects.raw('SELECT DISTINCT DATE_FORMAT(date_publish, '%Y-%m') as col_date FROM blog_article ORDER BY date_publish')
这样可以直接进行查询

自定义文章model的管理器,因为想要实现按年月吧文章归档的操作实现不了,所以自定义一个model来实现这个功能
有两种方式 
1:新加一个数据处理的方法
2.改变原有的queryset,就是重新定义这个方法,改变这个方法的返回
主要使用第一种方法
在models.py里面自定义Model管理器
class ArticleManager(models.Manager):

distinct_date_list = []

    def distinct_date(self):

date_list = self.values('date_publish')
#把日期的结果取出来
for date in date_list:
date = date['date_publish'].strftime('%Y%m文章存档')
if date not in distinct_date_list:
distinct_date_list.append(date)
return distinct_date_list

在Article的类中进行设置
objects = ArticleManager()
再views.py里面进行设置archive_list = Article.objects.distinct_date()

在base.html当中进行设置

<ul>
{% for archive in archive_list %}
<li>
<p><span class="tutime font-size-18"><a href=''>{{ archive }}</a></span></p>
</li>
{% endfor %}
</ul>
这样设置后网页上不会出现需要显示的归档信息,原因是编码问题
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
导入这个在models.py里面就可以了
http://blog.csdn.net/crazyhacking/article/details/39375535
http://blog.csdn.net/intel80586/article/details/8566057
python在解码的时候默认 以ASCLL码的方式进行解码

靠,今天实在是太粗心了,好恶心,就这么几分钟就能搞定的事情,花了我近一个小时,日
url(r'^archive/$',archive,name='archive') 
url配置的时候,前面要加上 ^ 后米加上/$  $不会影响传入的参数

配置archive.html
复制了index.html到archive.html当中,在views.py写下archive的函数,
在url当中进行引用,再到base.html当中进行设置
<p><span class="tutime font-size-18"><a href='{% url 'archive' %}?year={{ archive | slice:":4" }}&month={{ archive | slice:"5:7" }}'>{{ archive }}</a></span></p>
使点击分类文章时会跳转到archive.html当中,
再到views.html当中进行设置其逻辑结构
将index函数里面的分页查询的代码拷贝下来,就可以显示内容了
article_list = Article.objects.filter(date_publish__icontains=year+'-'+month)
修改查询的操作,这样只会照到指定参数的内容
到archieve.html当中做一些修改
<h2>{{ request.GET.year }}/{{ request.GET.month }}归档文章</h2>
发现在这里也可以使用传进来的参数
这里需要传入参数,因为QuerySet查询是惰性的,不会一下子查询出所有的记录只会查询出当前页面的内容,所以当跳转页面的时候,应该重新传入参数


重构代码:将重复的代码提取出来
卧槽,今天有点不顺啊,url(r'$',index,name='index'),这个前面不加^这个,然而刚刚我加上了,就报了一个404错误

把index和archive里面相同的代码提取出来放到global_settings里面

def global_setting(request):
#分类信息获取(导航数据)
category_list = Category.objects.all()
#文章归档数据
archive_list = Article.objects.distinct_date()
return {
'category_list':category_list,
'archive_list':archive_list,
'SITE_NAME':settings.SITE_NAME,
'SITE_DESC':settings.SITE_DESC,
}
还有一些数据也可以放到global_settings里面
如:广告数据,标签云数据,友情链接数据,文章排行榜数据

优化url:
当app多了的时候维护url变得困难,所以就选择在每个app下面建立url进行优化这种操作
复制工程下面的url到app当中,在工程当中:删除工程url当中app相关url改为include在本项目中
所做的修改是:url('^',include(blog.urls)) 还要导入includefrom django.conf.urls import url,include
app url  删除相关引入import只保留和app相关的url和import,

在views.py里面封装分页代码:
因为函数index和函数archive都有分页代码,所以可以把分页代码分装成一个函数来引用
def getPage(request,article_list):
paginator = Paginator(article_list,2)
try:
page = int(request.GET.get('page',1))
article_list = paginator.page(page)
except (EmptyPage,InvalidPage,PageNotAnInteger):
article_list = paginator.page(1)
return article_list
因为始终是对取出来的内容进行的修改所以就直接返回article_list,在article_list当中,还需要用到request,
所以这里需要传入request
archive.html和index.html都有上一页,下一页,所以可以Include提取出来
新建一个pagination.html把分页的代码直接复制进去,在到相应的位置,以{% include 'pagination.html' %}代替
然后发现archive的页面在按下一页后,参数没有传递过去,所以需要一个判断拼接字符串
文章排行:order_by()需要指定字段,不能这样使用Article.objects.all().order_by()
选择将文章进行分组,然后使用count函数

我发现凡是涉及到显示数据内容,都会牵扯到数据库操作,不一定,可以是settings里面设置的全局变量

return {
'category_list':category_list,
'archive_list':archive_list,
'SITE_NAME':settings.SITE_NAME,
'SITE_DESC':settings.SITE_DESC,
}
#站点基本信息设置
SITE_NAME = settings.SITE_NAME
SITE_DESC = settings.SITE_DESC
comment_count_list = Comment.objects.values('article').annotate(comment_count=Count('article')).order_by('-comment_count')
article_comment_list = [Article.objects.get(pk=comment['article']) for comment in comment_count_list]
return locals()
经验证,comment['article']为Article当中的id编号

在到base.html当中进行修改
<ul>
{% for article in article_comment_list %}
<li><a href="/" target="_blank">{{ article.title | slice:':15' }}</a></li>
{% endfor %}
</ul>
comment_count_list = Comment.objects.values('article').annotatennotate(comment_count=Count('article')).order_by('-comment_count')
.annotate的使用方法,Count的使用方法,return locals()可以直接返回当前作用域的变量,所以可以把里面的键值对的形式写成变量的形式,
article_comment_list = [Article.objects.get(pk=comment['article']) for comment in comment_count_list]
以数组的方式返回排完序的文章对象

自定义过滤器:
DoseNotExist异常,如果使用get没有获得对象,那么返回一个DoseNotExist异常
safe过滤器,把html转换成页面信息,不会直接打印出来
在templatetags包里面定义一个html使用的时候需要加载到html当中
在此html当中
from django import template
register = remplate.Library()

@register.filter
def month_to_upper(key):
    return[] [key.month-1]

register.filter('month_to_upper',month_to_upper)


浏览排行:
浏览量可以直接从Article的click_count中取出,所以可以直接通过取出Article所有对象然后对click_count进行排序即可

评论排行:
评论排行和浏览排行不同,Comment和Article是关联表,需要进行间接的排序,这里需要讨论一下

标签云:
 标签有一个Tag的类,子表是Article,所以可以在把tag_list取出放到global当中,然后在views.py当中定义tag函数,当点击tag的时候可以进行跳转,所以还要一个tag.html,在tag函数中主要是取出Article的对象,其它不变,筛选条件是,先取出Tag对象,取出Tag的点击对象,当点击的时候,应该把点击标签的id传过去,再取出对应的Article
友情链接:
友情链接的数据都已经写好了,所以可以直接在global当中取出Links的对象
广告:
<img id="slide-img-{{ ad.id }}" src="uploads/{{ ad.image_url }}" 
图片的src目前有三种情况
1:绝对路径
2:静态文件的相对路径<img id="slide-img-1" src="{% static 'images/a1.jpg' %}"  alt="" />
3:上传文件的路径<img id="slide-img-{{ ad.id }}" src="uploads/{{ ad.image_url }}"  直接写uploads文件夹加上传文件地址相当于就是绝对路径
src="../uploads/{{ ad.image_url }}"这里面需要加引号,写的就是绝对路径

引用关联外键里面的内容:
class Article(models.Model):
date_publish = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
user = models.ForeignKey(User, verbose_name='用户')
article = Article.objects.get(pk=id)
{{ article.user.username }}




bolg项目的更多相关文章

  1. 对MVC的理解

    摘要:本文主要谈到了对PHP开发中MVC开发模式的理解. 当用户通过url触发命令时,例如url=http://control.blog.sina.com.cn/admin/article/artic ...

  2. web框架---django

    15:31:14一.web框架1.框架:即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. ...

  3. Travis-CI自动化测试并部署至自己的CentOS服务器

    一直都想自己部署一下自动化测试部署,在了解了Travis-CI之后终于准备在这次和小伙伴一起做的一个博客类网站实验下了. 因为这是一个前后端分离的项目,所以我这里只管前端工程的自动化部署,前端主要用V ...

  4. (八)play之yabe项目【身份验证】

    (八)play之yabe项目[身份验证] 博客分类: 框架@play framework   添加身份验证 play提供了一个模块-Secure(安全模块),用来做身份验证 允许Secure模块 修改 ...

  5. fw: 专访许鹏:谈C程序员修养及大型项目源码阅读与学习

      C家最近也有一篇关于如何阅读大型c项目源代码的文章,学习..融合.. -------------------- ref:http://www.csdn.net/article/2014-06-05 ...

  6. Fis3前端工程化之项目实战

    Fis3项目 项目目录结构: E:. │ .gitignore │ fis-conf.js │ index.html │ package.json │ README.md │ ├─material │ ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  8. 最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目

    最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目 最近一个来自重庆的客户找到走起君,客户的业务是做移动互联网支付,是微信支付收单渠道合作伙伴,数据库里存储的是支付流水和交易流水 ...

  9. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

随机推荐

  1. C语言中fgetc函数返回值为什么是int?

    学习C语言的,文件操作,大都会用到它. 它的函数原型: 这个函数的返回值,是返回读取的一个字节.如果读到文件末尾返回EOF.EOF其实就是一个宏#define EOF (-1)表示-1.既然返回的是一 ...

  2. spark-streaming-kafka-0-10源码分析

    转发请注明原创地址http://www.cnblogs.com/dongxiao-yang/p/7767621.html 本文所研究的spark-streaming代码版本为2.3.0-SNAPSHO ...

  3. Linux操作系统下/etc/hosts文件配置方法

    1.关于/etc/host,主机名和IP配置文件 Hosts - The static table lookup for host name(主机名查询静态表) hosts文件是Linux系统中一个负 ...

  4. 459. Repeated Substring Pattern【easy】

    459. Repeated Substring Pattern[easy] Given a non-empty string check if it can be constructed by tak ...

  5. Scrapy爬虫入门系列3 将抓取到的数据存入数据库与验证数据有效性

    抓取到的item 会被发送到Item Pipeline进行处理 Item Pipeline常用于 cleansing HTML data validating scraped data (checki ...

  6. 【转】Monkey测试4——Monkey命令行可用的全部选项

    Monkey命令行可用的全部选项 常规 --help 列出简单的用法. -v 命令行的每一个-v将增加反馈信息的级别. Level 0(缺省值)除启动提示.测试完成和最终结果之外,提供较少信息. Le ...

  7. Python 之 ImportError: No module named ***

    假设想使用非当前模块中的代码,须要使用Import.这个大家都知道. 假设你要使用的模块(py文件)和当前模块在同一文件夹.仅仅要import对应的文件名称就好,比方在a.py中使用b.py: imp ...

  8. IE的卸载之路(折腾1个多月,记录下。。)

    IE 9: FORFILES /P %WINDIR%/servicing/Packages /M Microsoft-Windows-InternetExplorer-*9.*.mum /c “cmd ...

  9. Python:简述 线程、进程和协程

    Python线程 定义:Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- impor ...

  10. 那些可爱的 Linux 命令

    环境 root@15b883:~# uname -a ##需要是Ubuntu环境 Linux 15b883 --generic #- :: UTC x86_64 x86_64 x86_64 GNU/L ...