学习Django(二)

添加用户注册、登录、管理等功能

数据表的建立

Django以App的目录名为前缀,然后用_连接每一个模型的小写形式,例如easy_note这个App里面 有名为Note的模型,Django就会建立名为easy_note_note的数据表,因此不要随意改变App的名字

Django模板默认<br>无效

因为Django的模板系统在渲染的过程中,对html标签进行了转义,<br>实际上变成了&ltbt&gt, 但是在chrome的element面板中看到的是<br>,因为它自动将转义符号翻译回来了,而不是原始的 HTML源代码,这里禁用掉Django模板的自动转义就好:{{ var|safe }}加上safe标记就行。

Python中的异常

try except 语句用于异常的处理,参考 except <ErrorName> <AppendMessage>:用于捕获指定的异常及该异常附带的信息,BaseException 包括了所有的异常。

碰到的问题

关于模板文件的加载顺序

模板文件会按照TEMPLATE_LOADERS里面注册的顺序调用加载器来加载,默认的 'django.template.loaders.filesystem.Loader'按照TEMPLATE_DIRS中注册的路径来查找文件, 'django.template.loaders.app_directories.Loader'则是自动的在各个app根下面的templates 目录里面查找。

Mixing Django with Jinja2 without losing template debugging

参考 这个还是用到了coffin,于是干脆直接用coffin算了,参看这篇 一开始还对比着原先的Loader来修改jinja2_django,结果发现是徒劳的,只好用coffin了,唉。。。

coffin居然也有这个问题,尼码,用了coffin.shortcuts.render_to_response,所有的 调试信息都木有了!还是换回原先的jinja2_django_loader了,至少还能保留对app下模板查找 路径的信息

解决csrf的限制来使用POST方法处理表单

关键是在生成的form中,加入csrf_token(由Django生成),因此,在调用生成表单页面的 render_to_response('registration/signup.html', c)方法时,传入包含csrf_token变量 的Context,其简单方法就是在原有的Context变量c的基础上,调用c.update(csrf(request))官方文档

坑爹的关键字参数

Django模型层查找数据库的API所采用的是关键字参数,即User.objects.get(username='wangyu') 这就意味者我将username用变量来替代是错误的,这个问题导致我数据库明明有字段了,却还是返回允许, 之后只好硬编码来解决了,非常丑陋

无限长度的字符串

一开始以为用的是models.CharField(max_length=None),结果在syncdb的时候报错: easynote.note: "data": CharFields require a "max_length" attribute that is a positive integer. Google之网上有人说应该用TextField(出处

后台重定向提示 XXX didn't return an HttpResponse object

在views.py中的处理函数中,最后必须要返回HttpResponse对象,render_to_response等函数会 返回HttpResponse对象,如果需要进行重定向,那么必须使用return redirect('obj_url')

[2013-04-17]

Python的参数

位置参数 VS 关键字参数

  • 位置参数调用,参数的顺序确定了传入的值被赋给哪个参数
  • 关键字参数调用,指定参数的名字和传入的值来调用

下列调用方式等价

#定义
def sell(item, price, quantity):
    print "Selling %s unit(s) of %s at %s" % (quantity, item, price)

sell('Socks', '$2.50', 6)
sell(item='Socks', price='$2.50', quantity=6) #可以乱序
sell(quantity=6, item='Socks', price='$2.50')
...
sell('Socks', quantity=6, price='$2.50') #可以混合使用

Python中的可变参数

  • *args参数运行时,捕获所有位置参数,组成Tuple
  • **kwargs运行时,捕获所有关键字参数,组成Dict

例子

def foo(*args, **kwargs):
    print "Positional arguments are:"
    print args
    print "Keyword arguments are:"
    print kwargs

 >>> foo(1, 2, 3)   #全部被*args捕获
 Positional arguments are:
 (1, 2, 3)
 Keyword arguments are:
 {}
 >>> foo(1, 2, name='Adrian', framework='Django') #关键字参数被**kwargs捕获
 Positional arguments are:
 (1, 2)
 Keyword arguments are:
 {'framework': 'Django', 'name': 'Adrian'}
[2013-04-17]

学习Django(一)

摘要

The Django Book前七章的学习笔记,以及实践中碰到的问题

一些小技巧

快速调试

assert False能出发Django的错误页面,可以查看局部变量核程序语句

app和project

系统对app有一个约定: 如果你使用了Django的数据库层(模型),你 必须创建一个Django app

应每次都给成功的POST请求做重定向

这就是web开发的最佳实践。

views.py(视图)中不要硬编码URL

把URL逻辑放在了视图中并不优雅,因为URL的变更意味着需要对视图作出相应修该。 优雅的解决方法是,利用URLconf从顶向下的解析顺序这个特点,在URLconf中进行URL的处理

Django中的MVC -- MTC

  • M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  • V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

数据模型

使用数据库API

  1. 创建APP:python manage.py startapp books,创建app目录
  2. 在models.py编写models层(数据存取层),相当于创建数据库,class Publisher(models.Model): 实现models.Model的子类:Publisher。
  3. 在project中启用该app,settings.py里面'INSTALLED_APPS=()'中加入'books',
  4. python manage.py validate验证无错后,python manage.py sqlall books来生成实现 数据层的创建数据表的数据库语句。(Django会自动根据settings里面配置的数据库生成对应的语句)
  5. python manage.py syncdb向数据库提交上述指令,创建数据表(它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并不能将模型的 修改或删除同步到数据库;如果修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。) 6 然后,就可以from books.models import Publisher引入Publisher模型,调用 p1 = Publisher(key1=value1, key2=value2, ...)之后,再调用p1.save()就可以将数据写入 数据库,Publisher.objects是数据库中和Publisher相关的数据集合的API, Publisher.objects.all()获取全部对象(使用Publisher.objects.create(...)可以创建一条 记录并且立即更新到数据库中,而不必在调用save())

Tips:

  • 实现models.Model类的 unicode():方法,可以打印更有意义的信息。(该方法定义了一个对象 的字符串表示)
  • 实现class Meta:ordering = ['name']属性设定默认的排序方式
  • 字段可选:blank=True,如email = models.EmailField(blank=True)

数据查询API:objects

  • all()可以返回全部记录
  • filter(key1=value1, key2=value2)相当于条件查询,同时, key__contains='', icontains(大小写无关的LIKE),startswith和endswith, range如其字面所述
  • get()获取单个对象,当存在多个结果或不存在结果时,就会抛出异常
  • order_by()进行排序,在value前加-号表示逆向,可直接链在filter()语句后面使用
  • 语句最后指定[N]可以限定查询返回条目
  • update(key=value)更新某一条记录,而设定get()返回的对象的属性后再save()会全部更新,不安全。
  • delete()删除

数据管理后台 Admin

它读取Model中的元数据,然后提供一个强大而且可以使用的界面,网站管理者可以用它立即工作。

contirb包

django.contrib是一套庞大的功能集,它是Django基本代码的组成部分,Django框架就是由众多包含附加组件(add-on)的基本代码构成的。 包括admin,auth,sessions,comments等功能

开启Admin

  1. 在settings.py中的INSTALLED_APP中加入django.contirb.admin,并确保 auth,contenttypes,sessions开启(admin所需),
  2. 确保MIDDLEWARE_CLASSS包含'django.middleware.common.CommonMiddleware''django.contrib.sessions.middleware.SessionMiddleware''django.contrib.auth.middleware.AuthenticationMiddleware'
  3. 运行python manage.py syncdb生成数据表
  4. 运行python manage.py createsuperuser创建管理员帐号
  5. urls.py里面添加对/admin/路径的解析
  6. 添加需要接续的Model:在app模块下创建admin.py,然后输入:admin.site.register(Publisher) 并引入相应的admin和Publisher.

请求信息: GET, POST etc ...

从request对象中获取数据

  • URL相关:pathget_hostget_full_pathis_secure
  • META(Dict类型)下面包含:HTTP_REFERERHTTP_USER_AGENTREMOTE_ADDR,用try/except 或者get()语句来访问,避免key不存在的情况
  • GET(类Dict对象)
  • POST

Django自带form系统

  1. from django import forms
  2. class ContactForm(forms.Form):实现该类,添加比如 email = forms.EmailField(requied=False)等表单字段
  3. ContactForm()返回一个对象,可以提供不同形式的HTML, ContactForm({'field1': 'value1', ...})返回的对象可以验证数据合法性,同时f.cleaned_data 会返回相应的Python类型数据

碰到的问题

指定绝对路径的模板路径

Django的TEMPLATE_DIR选项要求必须是绝对路径,因此,使用下述语句来获取绝对路径 os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),__file__ 变量会被自动设置为代码所在的 Python 模块文件名,即当前文件路径名。 之前由于错误操作,在TEMPLATE_LADERS里面加入了空字符串选项,导致Django报错,排查了好久...

使用jinja2模板

网上都说Django自带的模板弱爆了,于是尝试下推荐的jinja2模板。除了安装jinja2之外,需要实现 jinja2的Loader来使用Django自带的模板系统的API,参考此文 但是,它的env = jinja2.Environment(loader=jinja2.FileSystemLoader(app_template_dirs)) 语句有问题,使用app_template_dirs并不包含TEMPLATE_DIRS中设定的路径,将这部分替换成 settings.TEMPLATE_DIRS并将脚本放在项目的根目录下面,然后设定TEMPLATE_LOADERS中注释 掉其他该选项,并加入'jinja2_for_django.Loader',就可以了。

ManyToManyField的读写

参考

在读写ManyToManyField类型的字段时,要把它当成一个Model来操作,比如authors = models.ManyToManyField(Author) 那么在写入的时候,要先save()好新建Model比如t1,然后t1.authors.add()插入,t1.authors.all() 读取,ti.author.creat()新建多个...详细参看链接

urls.py书写总结

  • 使用其他文件内的配置来解析某些URL,使用url函数(据我估计应该是url函数将第一个前缀参数与 include提供的urls.py内的条目结合起来,进行判断...) url(r'^graphic/', include('graphic.urls'))
  • 书写正则时,一定要加上/$,不然Django会将后面的任意内容都匹配到这个视图去,造成混乱,/ 则是url结束的标志,比如使用data/$,由于Django会自动加上/因此访问data会自动被Django转换 成data/进行适配,访问data/或者data均可,而使用data$时,Django不会自动将data/转换成 data进行适配 ,也就是说此时只能通过data进行访问,data/是无法访问的。建议使用data\/$ 的形式。

csrftoken导致的POST请求403 forbidden

今天在测试时,发现ipad上的POST请求被403了,排查了以下原来是cookie中并没有csrftoken,那么 Django在什么情况下才会设置这个cookie呢?

  1. 模板文件中使用了{\% csrftoken \%}时,Django发现token被渲染,于是通过CsrfViewMiddleware 下的processresponse在浏览器中设置key为csrftoken的Cookie,
  2. 处理GET请求时,使用request.META["CSRF_COOKIE_USED"] = True强制更新Cookie中的 csrftoken值

参考链接

[2013-04-14]

NFS安装小记

今天打算捣鼓个NFS玩玩,感受一下远程共享的便捷 鸟哥的私房菜-NFS篇

安装并启用NFS程序

  1. yum install nfs-utils,会自动将依赖的rpcbind程序也安装好
  2. service rpcbind start,必须要先启动rpcbind
  3. service nfs start,启动hfs进程

配置NFS目录

/etc/exports记录了NFS对应的目录设置

/home/wy hellfe.com(rw) localhost(rw)

这其中指定的是覆盖默认设置的设置,/var/lib/nfs/etab文件包含了实际的设置(包含默认设置) 最好将共享的文件所有者和用户组设置成nfsnobody:nfsnobody,这样就不怕权限问题无法修改 修改完该文件后,需要重启NFS服务(比较麻烦)或者exportfs -arv来生效

server端测试状态

  • showmount -e localhost显示某主机上共享的目录资料
  • showmount -a显示本机连接的NFS

配置防火墙

主要参考这个

防火墙需要打开以下端口:

  1. TCP/UDP 111 - RPC 4.0 portmapper
  2. TCP/UDP 2049 - NFSD (nfs server)
  3. Portmap static ports, Various TCP/UDP ports defined in /etc/sysconfig/nfs file.

其中第三项通过在/etc/sysconfig/nfs里面设置,其实就是去掉注释就好:

LOCKD_TCPPORT=32803
LOCKD_UDPPORT=32769
MOUNTD_PORT=892
RQUOTAD_PORT=875
STATD_PORT=662
STATD_OUTGOING_PORT=2020

在防火墙规则正文中,加入如下条目:

-A INPUT -s 0.0.0.0/0 -m state --state NEW -p udp --dport 111 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 111 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 2049 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 32803 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p udp --dport 32769 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 892 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p udp --dport 892 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 875 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p udp --dport 875 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p tcp --dport 662 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -m state --state NEW -p udp --dport 662 -j ACCEPT

客户端挂载

客户端也需要安装并运行nfs程序,然后执行下述命令挂载即可: mount -t nfs hellofe.com:/tmp/test /tmp/remote

碰到的问题

Stale NFS file handle 报错

client端mount上了server端的directory之后,server端将这个directory重新export或者 delete之后,就会报上述错误.参考
解决方法: 重启客户端hfs进程service hfs restart

操作挂载文件时提示 "Permission Denied"

原因:NFS共享的DIR所有者是root,而默认情况下,即使客户端使用root身份操作,也会被 rootsquash自动设定成nfsnobody,指定noroot_squash属性就好

mount.nfs: access denied by server while mounting

客户端在挂载的时候报该错,网上说需要设定共享DIR的insecure参数,允许客户端从大于 1024的tcp/ip端口连接服务器。也就是说默认的是secure参数,限制客户端只能从小于1024 的tcp/ip端口连接nfs服务器,而我的客户端在mount的时候,使用了大于1024的端口,自然 被服务器deny了,加了insecure之后OK了。

挂载的文档没有权限操作

一般NFS的文件夹的所有者和最后连接的客户端的用户是不同的,这就导致了绝大多数情况下 直接mount NFS 文件夹之后没有写权限,需要进行用户映射。选项如下:
+ allsquash 将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody) + noallsquash 与allsquash取反(默认设置); + rootsquash 将root用户及所属组都映射为匿名用户或用户组(默认设置) + noroot_squash 与rootsquash取反 + anonuid=xxx 将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx) + anongid=xxx 将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为 本地用户组账户(GID=xxx)

服务器上的账户对应的uid和gid分别是500,设置all_squash参数,去掉其他的squash 并设置好anonud=500和anongid=500就可以了。

Fedora下面开机自启动问题

直接systemctl enable nfs.service会报Failed to issue method call: No such file or directory错误,原因是Fedora下面nfs开机自启动对应的是nfs-server.service,再 试一次,ln -s '/usr/lib/systemd/system/nfs-server.service' '/etc/systemd/system/multi-user.target.wants/nfs-server.service'成功!

[2013-04-13]


安装PPTP来翻墙

今天让吴妞买了Linode的服务器,果然速度飞快。ssh过去操作基本上没有延迟。(PS:一开始给的IP死活 ssh不上去,发了个ticket换了两个ip终于可以了)

什么是VPN?

VPN可以这样理解,Linux客户端使用一个虚拟网络设备ppp0(Windows客户端也可以理解成VPN虚拟网卡) ,连接到服务器的虚拟网络设备ppp0上,这样客户端就加入了服务器端ppp0所在的网络。localip就是可以 分配给服务器端ppp0的IP地址,remoteip则是将要分配给客户端ppp0(或者虚拟网卡)的。

安装流程

详细参考 简易参考

1 验证内核是否加载了MPPE模块

网上说:modprobe ppp-compress-18 && echo MPPE is ok显示MPPE ok即说明支持,但是实际输出 确是FATAL: Module ppp_mppe not found.难道是不支持?找了下:

Kernel version 2.6.15及以上版本内核内置了MPPE的支持,CentOS 5的kernel是2.6.18, 所以不需要再安装MPPE模块。CentOS 5自带的ppp-2.4.4-1.el5也支持MPPE。

检测PPP是否支持MPPE的方法:strings '/usr/sbin/pppd' |grep -i mppe | wc --lines输出 大于30就好,我的输出42,哈哈,OK的!

2 安装软件

  1. yum install ppp
  2. wget http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.3.4-2.el6.i686.rpm并安装
  3. yum install iptables

3 配置文件

PPP配置文件

/etc/ppp/options.pptpd主要配置选项如下:

name pptpd #服务名称
refuse-pap #拒绝、接受的加密方式
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
ms-dns 8.8.8.8 #指定VPN使用的DNS服务器 + + +
ms-dns 8.8.4.4 #为Google Public DNS  + + +
proxyarp
lock
nobsdcomp
novj
novjccomp
nologfd

/etc/ppp/chap-secrets设定账户和密码,用明文存储VPN客户的用户名、服务名称、密码和IP地址范围,每行一个账户:

username1    pptpd    passwd1    * #pptpd对应上述选项中设置的服务名称 + + +
username2    pptpd    passwd2    * #最后一列限制客户端IP地址,星号表示没有限制。

pptpd配置文件

/etc/pptpd.conf是PPTP的配置文件,主要选项如下:

option /etc/ppp/options.pptpd
logwtmp
localip 192.168.0.1
remoteip 192.168.0.207-217
  • option选项指定使用/etc/ppp/options.pptpd中的配置
  • logwtmp表示使用WTMP日志。
  • localip和remoteip所处的IP段可以随意些指定,但其范围内不要包含实际网卡eth0的IP地址。 一般情况下,使用上面配置文件中的配置就好使了,你需要做的只是把192.168.0.207-217这个IP区间 修改成你喜欢的192.168.0.a-b

4 打开内核的IP转发功能

要使VPN服务器可以作为网络请求的中转代理,能够使客户端通过VPN访问Internet,还需要开启内核的IP转发功能。 编辑/etc/sysctl.conf配置文件,修改成net.ipv4.ip_forward = 1,然后执行sysctl -p 生效

5 启动pptpd守护进程

6 配置iptables放行和转发规则

配置防火墙有三个目的

  • 设置默认丢弃规则,保护服务器的安全;
  • 放行我们允许的数据包,提供服务;
  • 通过配置nat表的POSTROUTING链,增加NAT使得VPN客户端可以通过服务器访问互联网

跟PPTP VPN相关的服务

  • 允许GRE(Generic Route Encapsulation)协议,PPTP使用GRE协议封装PPP数据包,然后封装成IP报文
  • 放行1723端口的PPTP服务
  • 放行状态为RELATED,ESTABLISHED的入站数据包(正常提供服务的机器上防火墙应该都已经配置了这一项)
  • 放行VPN虚拟网络设备所在的192.168.0.0/24网段与服务器网卡eth0之间的数据包转发
  • 为从VPN网段192.168.0.0/24转往网卡eth0的出站数据包做NAT

重启iptables服务

Iptables error – Setting chains to policy ACCEPT: security raw nat mangle filter [FAILED] 错误的解决办法

碰到的问题

感觉还第二篇简介实用。

  1. 连接失败,查看/var/log/message发现是:MPPE required but peer negotiation failed 之后连接就被终止了,原来是客户端连接的时候忘记勾选MPPE加密选项了
  2. 连上去无法上网:

增加 /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.9.0/24 -j MASQUERADE 后,查看iptables nat表,iptables -L -t nat,没有条目出现。 多试几次,有表项出现,就好了。原文

照着第二篇的教程,重新设置两了下iptables规则就好了,OK!能用VPN啦~

[2013-04-11]

开发chrome插件时学习PHP的一些笔记

关于require()和include()

PHP执行require()和include()语句时,相当于在当前位置分隔代码,然后直接将文件的内容写入到当前 文件中。

require()函数包含进来的内容被当成当前文件的一个组成部分,所以当包含进来的文件有语法错误或者 文件不存在的时候,当前文件的PHP脚本都不再执行. include()函数相当于指定这个文件的路径,当被包含的文件有错时,不会影响到本身的程序运行. include函数可以进行判断是否包含,而require则是不管任何情况都包含进来

检查key是否存在

检查数组是否存在某个$key,使用arraykeyexists($key, $array);
检查对象是否存在某个$key,使用isset($object->$key)。
链接 用上述方法去判断而不是直接$_POST[$key]可以避免不存在时的Notic

[2013-04-08]

毕设中学习MySQL的一些笔记

权限相关

参考链接

创建帐号

格式为:GRANT 权限 ON 库名.表名 'user'@'连接的主机名' IDENTIFIED BY '密码'

例子

GRANT ALL ON *.* TO 'reader'@'localhost' IDENTIFIED BY '314428'创建了一个对所有数据 库和数据表都有所有权限的账户reader,其密码是314428

注意事项

  • 主机名用%表示任何,可用192.168.0.%限定局域网
  • 修改完权限以后一定要刷新服务flush privileges,或者重启服务。
  • MySQL里面的用户包含主机的信息,即一个用户要和其主机关联起来,比如要删除刚才创建的reader用户, 应使用drop user reader@localhost,直接drop user reader实际上是执行了drop user reader@%, MySQL自动加上所有域的标识符%。

ERROR 1045 (28000) 错误排查

我用GRANT select, insert, update, delete on python.* TO 'reader'@'%' IDENTIFIED BY '314428'; 语句创建了一个reader@%的账户,也即能支持所有主机上的reader用户登录,但是在用mysql -u reader -p 连接时,却报Access denied for user 'reader'@'localhost' (using password: YES)错误。

后来网上找了下,说是加上 -h serverIP 就可以了,于是mysql -u reader -p -h 192.168.1.112, 果然可以!
找了好久,终于找到原因:

删除那条 user 为 空、host 为 localhost 的记录。你新添加的记录被它匹配了,根本匹配不到。

MySQL检查客户端登录的主机名\/用户名是有一定顺序的,优先匹配host,然后才匹配user。 匹配host时,又要求优先匹配确定性更大的host。比如,%.test.com 优先于 %.com,%.com 优先于 %,不带通配符的host优先于带通配符的host。 查看原文

在本例中,mysql -u reader -p是以reader@localhost的身份登录的,在MySQL的user表里面,又 存在localhost的匿名用户的记录,也就是说:localhost匹配到了一条记录后,就直接去匹配user,而 不会因为无法匹配到user再回过头来匹配主机为%的记录,这就导致了mysql -u reader -p实际上是 以匿名的方式来登录的,即等价于mysql -p,直接输入空密码就可以登录了。
mysql -u reader -p -h 192.168.1.112不会适配user表里面的localhost记录,转而选择了% 记录来验证,因此可以正常登录,因此-h 127.0.0.1同样会报错!

忘记root密码重置

  1. 关闭mysqld服务 killall -TERM mysqld
  2. 以不检查权限的方式启动 mysqld_safe --skip-grant-tables &
  3. 用空密码方式使用root用户登录 MySQL mysql -u root
  4. 修改root用户的密码 update MySQL.user set password=PASSWORD('新密码') where User='root';
  5. 更新生效 flush privileges;
  6. 重新启动MySQL,就可以使用新密码登录了。

查看当前权限

show grants查看当前用户权限,show grants for dba@xxx查看对应用户的权限

撤销用户权限

REVOKE ALL ON *.* from dba@localhost;即将grant to变成revoke from

查看用户

  1. use mysql
  2. select * from user

删除用户

DROP USER 用户名;

修改密码

UPDATE USER SET PASSWORD=PASSWORD('000000') WHERE USER='xxx';

时间字段格式TIMESTAMP,DATETIME,INT

  • DATETIM和TIMESTAMP类型所占的存储空间不同,前者8个字节,后者4个字节,这样造成的后果是 两者能表示的时间范围不同。前者范围为1000-01-01 00:00:00 ~ 9999-12-31 23:59:59,后者范围 为1970-01-01 08:00:01到2038-01-19 11:14:07。所以可以看到TIMESTAMP支持的范围比DATATIME 要小,容易出现超出的情况.
  • 默认情况下,insert、update 数据时,TIMESTAMP列会自动以当前时间(CURRENT_TIMESTAMP)填充/更新。
  • TIMESTAMP比较受时区timezone的影响以及MYSQL版本和服务器的SQL MODE的影响
  • DATETIME和TIMESTAMP相对于int来说有一系列的时间函数可以用

所以一般来说,我比较倾向选择DATETIME,至于你说到索引的问题,选择DATETIME作为索引, 如果碰到大量数据查询慢的情况,也可以分区表解决。

MySQL多表查询

项目中,需要查询某一数据点的详细信息和所有数据点的数目,需要进行多表查询,最后写成的语句是

select recordid,datacount From ato_data 
LEFT JOIN ato_record_info on ato_data.trainid=ato_record_info.trainid 
WHERE ato_data.trainid = "CCATO01L" AND ato_data.time = "20120905_113012" 
AND g4 >= -9002 ORDER BY g4 LIMIT 1;

关于ERROR 1052 (23000): Column 'trainid' in where clause is ambiguous

这是因为多表查询的时候几个表中同时出现了某个相同的列名,而在查询条件WHERE后面又没有指定 是那个表,而引起的,又或者是查询结果里面有两个相同的列名,而没有指定是哪个表。使用的时候可以在 mysql查询前面加表名以避免出现错误(比如上面我就加了ato_data前缀,而选则的数据并没有出现重合, 因此可以不必加前缀)

多表连接 inner join, left join, right join, full join, cross join

  • inner join: 两表都满足的组合
  • full outer: 两表相同的组合在一起,A表有,B表没有的数据(显示为null)
  • A表 left join B表: 以A表为基础,A表的全部数据,B表有的组合
  • A表 right join B表: 以B表为基础,B表的全部数据,A表的有的组合。

语法参考这里

囧。。。经过测试,join操作会极大的增大查询时间,对于我这个不是最佳解决方案咯,还是放回到2个 query中去查询了。。。

发现一个奇怪的事情

查询时,加上LIMIT会缩短时间(一旦数量足够就会自动停止查询,因此时间会缩短),但是对于int类型 的数据,在查询时在数字两边加上引号,例如recordid="2873"比不加引号要快的多!,测试代码:

select recordid  From ato_data WHERE recordid="2873" AND trainid = "CCATO01L"
 AND time = "20120905_115616" ORDER BY recordid LIMIT 1;

真是奇怪。。好吧,经过测试没什么影响,估计是和计算机当时的运行情况相关,但是第一点还是有效的。

[2013-04-08]

a-beginners-introduction-to-http-and-rest

原文

文中观点

  • 资源URL应该是名词,否则不是RESTful。 是否使用URL来描述一个动作,是最基本的区分RESTful和non-RESTful系统的基础
  • URL越精确越好,用于定位资源的所有信息都应该由URL来提供,而不是在Request中包含信息,URL在 整个程序的响应中,扮演完整的映射角色
  • 用GET POST PUT DELETE来明确动作
[2013-04-08]

双系统重做windous启动菜单的恢复

今天发现win7电脑已经中毒了,声音很怪,而且上不了网,又到了2b这边,没啥事做,于是就准备重做下 系统,用了之前帮小马刻的光盘,安装很快,win8很赞,就是不知道怎么激活。。。

用u盘做grub2引导

  1. df -h命令查看一下u盘的盘符和挂载路径,分别为/dev/sdc1/run/media/wangyu/34F1-06DA
  2. sudo grub2-install --force --root-directory="/run/media/wangyu/34F1-06DA" /dev/sdc1 不报错就将引导程序安装到了u盘的根目录下面的boot文件夹下面
  3. 拷贝当前的grub2配置文件到u盘对应目录下面/boot/grub2/grub.cfg/boot/grub2/device.map

安装windous后修复grub2到MBR

  1. df -h找到/boot的盘符为/dev/sda13
  2. 将/boot挂载到系统中:mount /dev/sda13 /run/media/tempdir
  3. grub2-install --force --root-directory=/run/media/tempdir /dev/sda就创建了 /dev/sda13/boot/grub2/等文件,重新安装grub2到硬盘的主引导记录【MBR】里面。 (这时候有个问题就是grub2安装目录是/boot/boot/grub2/而不是原先的/boot/grub2, 可以通过指定--boot-directory来解决,默认是/boot/grub2)
  4. grub2-mkconfig -o /boot/boot/grub2/grub.cfg重新生成grub2配置文件,并拷贝相应的 device.map文件到grub2目录下即可

心得

用u盘装grub2实在是太方便了,而且步骤也很简单,这样就可以随意的重装windous系统了,哈哈

[2013-04-02]

新的系统和服务管理软件--systemd

简介

systemd 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本。systemd 的特性有:

  • 支持并行化任务;
  • 同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);
  • 利用 Linux 的 cgroups 监视进程;
  • 支持快照和系统恢复;
  • 维护挂载点和自动挂载点;
  • 各服务间基于依赖关系进行精密控制。

systemd可以替换service(启动服务)和chkconfig(开机自动运行服务) 查看详情

service

startstoprestartreload(重载配置)condrestart(如果在运行则重启) status(查看运行状态)

chkconfig

  • chkconfig xxx on(设定启动运行) -> systemctl enable xxx.service
  • off
  • chkconfig xxx(直接chkconfig查看当前设置)
  • chkconfig --list(输出在个运行级别下服务的启动和禁用情况)

工作流程

  1. 系统启动时,systemd默认激活default.target(按照依赖关系激活服务和调用其他unit)

常用指令

  • systemd-cgls:树形查看Linux控制组结构层次
  • systemctl:列出正在运行的服务和其他
  • system is-enable xxx.service:查看某一服务是否开机自启动
  • system isolate runlevelN,target:切换到第N运行级
  • 改变默认运行级别:1)rm /etc/systemd/system/default.target 2)ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
  • systemctl list-units --type service列出所有loaded & active的unit,--all查看loaded的unit
  • systemctl list-unit-files --type service列出所有安装的service类型的unit files列表

.service .target等配置文件的位置

/usr/lib/systemd/system/*
配置的实质是将配置文件软链接到/etc/systemd/system/下面

实例

mysql开机自启动

sudo systemctl enabele mysqld

ln -s '/usr/lib/systemd/system/mysqld.service' '/etc/systemd/system/multi-user.target.wants/mysqld.service'

[2013-03-30]

毕设中学习Node.js的一些笔记

nodejs处理二进制文件

Node 有一个二进制缓冲实现 Buffer,这个伪类(pseudo-class)提供了一系列处理二进 制数据的 API,简化了那些需要处理二进制数据的任务。缓冲的长度由字节数据的长度决定, 而且可以随机的设置和获取缓冲内的字节数据。 注意:Buffer类有一个特殊的地方,缓冲内的字节数据所占用的内存不是分配在 JavaScrpIt VM 内存堆上的,也就是说这些对象不会被 JavaScript 的垃圾回收算法处理, 取而代之的是一个不会被修改的永久内存地址,这也避免了因缓冲内容的内存复制所造成的 CPU浪费。

  • 可以用一个 UTF-8 字符串创建缓冲,像这样:var buf = new Buffer(‘Hello World!’);
  • 也可以用指定编码的字符串创建缓冲:var buf = new Buffer('8b76fde713ce', 'base64');
  • 如果没有数据来初始化缓冲,可以用指定的容量大小来创建一个空缓冲:var buf = new Buffer(1024); // 创建一个 1024(Byte) 的缓冲,此时缓冲的数据并没有被初始化成 0,而是随 机数据。
[2013-03-26]