My NoteBook¶
WebDAV安装¶
操作步骤¶
1. 安装apache¶
#安装apache
$ yum -y install httpd apr apr-util httpd-deve
#设置开机启动(可选)
$ chkconfig httpd on
#启动apache服务
$ service httpd start
#临时关闭防火墙(如果不关闭,则只能本机访问apache服务)
$ service iptables stop
2. 配置WebDAV模块¶
apache服务器已经集成了WebDAV模块,所以只需要启用该模块即可。
2.1 编辑/etc/httpd/conf/httpd.conf
$ vi /etc/httpd/conf/httpd.conf在文件的最后添加以下语句:
Include conf/webdav.conf #指定webdav的配置文件路径2.2 新建webdav配置文件
$ vi /etc/httpd/conf/webdav.conf将以下内容插入到文件中:
<IfModule mod_dav.c> LimitXMLRequestBody 131072 Alias /webdav "/var/www/webdav" <Directory /var/www/webdav> Dav On Options +Indexes IndexOptions FancyIndexing AddDefaultCharset UTF-8 AuthType Basic AuthName "WebDAV Server" AuthUserFile /etc/httpd/webdav.users.pwd Require valid-user Order allow,deny Allow from all </Directory> </IfModule>2.3. 创建访问目录
$ mkdir -p /var/www/webdav $ chown apache:apache /var/www/webdav2.4. 添加用户
$ htpasswd -c /etc/httpd/webdav.users.pwd test #根据提示输入密码2.5. 重启apache服务
$ service httpd restart
3. 测试¶
通过浏览器访问:访问本机 , 访问远程:http://hostip/webdav
CentOS6.6安装Openssh 7.3p1¶
前置条件¶
- 操作系统:CentOS6.6 mini安装版
- Openssh版本 7.3p1
- 安装所需组件
Zlib 1.1.4或者1.2.1.2或者更高(系统默认安装)
Openssl >= 0.9.8f < 1.1.0
Gcc,Make
yum install -y zlib-devel openssl-devel pam-devel yum install -y gcc* make
安装步骤¶
- 卸载现有openssh rpm包
rpm -e `rpm -qa|grep openssh`
- 上传或者下载tar包至
tmp/
下 - 解压
cd /tmp
tar -zxf openssh-7.3p1.tar.gz
进入openssh-7.3p1文件夹
cd openssh-7.3p1
- 编译安装
默认安装命令:
./configure
make
make install
在安装过程中 ./configure
可能会出现错误,点击查看 FAQ
将Openssh二进制文件安装到 /usr/local/bin
,配置文件在 /usr/local/etc
,server在
/usr/local/sbin
等,使用 --prefix
来定义不同的安装路径前缀,如下:
./configure --prefix=/opt
make
make install
以上命令,将安装到 /opt/{bin,etc,lib,sbin}
.你也可以指定个别的路径,例如:
./configure --prefix=/opt --sysconfdir=/etc/ssh
make
make install
以上命令,将安装到 /opt/{bin,etc,lib,sbin}
.但是配置文件在 /opt/etc/ssh
.
建议编译安装命令:
安装目录在 /usr/local
,配置文件在 /etc/ssh
.
./configure --with-pam --sysconfdir=/etc/ssh
make
make install
- 复制sshd文件到
/etc/init.d
cp /tmp/openssh-7.3p1/contrib/redhat/sshd.init /etc/init.d/sshd
- 修改启动文件
vi /etc/init.d/sshd
修改成自定义安装路径:
SSHD=/usr/local/sbin/sshd
if [ -x /sbin/restorecon ]; then
/sbin/restorecon /etc/ssh/ssh_host_key.pub
/sbin/restorecon /etc/ssh/ssh_host_rsa_key.pub
/sbin/restorecon /etc/ssh/ssh_host_dsa_key.pub
/sbin/restorecon /etc/ssh/ssh_host_ecdsa_key.pub
fi
注释这句 /sbin/restorecon /etc/ssh/ssh_host_key.pub
- 添加快捷方式
cd /usr/bin
ln -s -T /usr/local/bin/scp scp
ln -s -T /usr/local/bin/sftp sftp
ln -s -T /usr/local/bin/ssh ssh
ln -s -T /usr/local/bin/ssh-add ssh-add
ln -s -T /usr/local/bin/ssh-agent ssh-agent
ln -s -T /usr/local/bin/ssh-keygen ssh-keygen
ln -s -T /usr/local/bin/ssh-keyscan ssh-keyscan
- 启动sshd服务
service sshd start
- 增加服务到启动项
chkconfig --add sshd
chkconfig sshd on
配置Openssh¶
运行配置文件被存放在 ${prefix}/etc
或者你指定的 --sysconfdir
.(默认在 /usr/local/etc
)
Sphinx备忘单¶
这是一份奇妙的便签,关于你在Sphinx和ReST中需要用到的常见资料。你可以查看 这个文档的源码。
文本格式¶
你可以使用行间标记来标记文本成 斜体, 粗体,或者 monotype
。
你可以相当简单地展现代码块:
import numpy as np
x = np.random.rand(12)
或者之间将代码纳入进来:
from pylab import *
from matplotlib.patches import Ellipse
delta = 45.0 # degrees
angles = arange(0, 360+delta, delta)
ells = [Ellipse((1, 1), 4, 2, a) for a in angles]
a = subplot(111, aspect='equal')
for e in ells:
e.set_clip_box(a.bbox)
e.set_alpha(0.1)
a.add_artist(e)
xlim(-2, 4)
ylim(-1, 3)
show()
制作列表¶
生成列表是一件非常容易的事情。
制作表格¶
这里介绍了怎么样制作一张表格——如果你指向制作一张列表请看 制作列表 。
Name | Age |
---|---|
John D Hunter | 40 |
Cast of Thousands | 41 |
And Still More | 42 |
脚注¶
这段介绍一个脚注是如何制作的。[1] 如下代码,效果见脚注[1]:
Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
.. rubric:: Footnotes
.. [#f1] Text of the first footnote.
.. [#f2] Text of the second footnote.
制作超链接¶
你可以很容易的生成一个超链接到 新浪 或者到这篇文档的一个 小结 (见: 制作表格 ) 又或者到另外一个文档。
(未翻译)You can also reference classes, modules, functions, etc that are
documented using the sphinx autodoc facilites. For example,
see the module matplotlib.backend_bases
documentation, or the
class LocationEvent
, or the method
mpl_connect()
.
这个文档的源码¶
.. _cheat-sheet:
******************
Sphinx备忘单
******************
这是一份奇妙的便签,关于你在Sphinx和ReST中需要用到的常见资料。你可以查看 :ref:`cheatsheet-literal`。
.. _formatting-text:
文本格式
===============
你可以使用行间标记来标记文本成 *斜体*, **粗体**,或者 ``monotype``。
你可以相当简单地展现代码块::
import numpy as np
x = np.random.rand(12)
或者之间将代码纳入进来:
.. literalinclude:: ellipses.py
.. _making-a-list:
制作列表
=============
生成列表是一件非常容易的事情。
要点列表
-------------
这段介绍如何制作要点列表。
* point A
* point B
* point C
有序列表
------------------
这段介绍何如制作有序列表。
#. point A
#. point B
#. point C
.. _making-a-table:
制作表格
==============
这里介绍了怎么样制作一张表格——如果你指向制作一张列表请看 :ref:`making-a-list` 。
================== ============
Name Age
================== ============
John D Hunter 40
Cast of Thousands 41
And Still More 42
================== ============
脚注
=============
这段介绍一个脚注是如何制作的。[1]_ 如下代码,效果见脚注[1]::
Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
.. rubric:: Footnotes
.. [#f1] Text of the first footnote.
.. [#f2] Text of the second footnote.
.. _making-links:
制作超链接
============
你可以很容易的生成一个超链接到 `新浪 <http://sina.com.cn>`_ 或者到这篇文档的一个
小结 (见: :ref:`making-a-table` ) 又或者到另外一个文档。
(未翻译)You can also reference classes, modules, functions, etc that are
documented using the sphinx `autodoc
<http://sphinx.pocoo.org/ext/autodoc.html>`_ facilites. For example,
see the module :mod:`matplotlib.backend_bases` documentation, or the
class :class:`~matplotlib.backend_bases.LocationEvent`, or the method
:meth:`~matplotlib.backend_bases.FigureCanvasBase.mpl_connect`.
.. _cheatsheet-literal:
这个文档的源码
==================
.. literalinclude:: cheatsheet.rst
英文源码 [2]_
==================
.. literalinclude:: cheatsheet_eng_version.txt
.. rubric:: 脚注
.. [1] 这是一个脚注的内容。
.. [2] 英文源链接:http://matplotlib.org/sampledoc/cheatsheet.html#making-a-list
英文源码 [2]¶
.. _cheat-sheet:
******************
Sphinx cheat sheet
******************
Here is a quick and dirty cheat sheet for some common stuff you want
to do in sphinx and ReST. You can see the literal source for this
file at :ref:`cheatsheet-literal`.
.. _formatting-text:
Formatting text
===============
You use inline markup to make text *italics*, **bold**, or ``monotype``.
You can represent code blocks fairly easily::
import numpy as np
x = np.random.rand(12)
Or literally include code:
.. literalinclude:: ellipses.py
.. _making-a-list:
Making a list
=============
It is easy to make lists in rest
Bullet points
-------------
This is a subsection making bullet points
* point A
* point B
* point C
Enumerated points
------------------
This is a subsection making numbered points
#. point A
#. point B
#. point C
.. _making-a-table:
Making a table
==============
This shows you how to make a table -- if you only want to make a list see :ref:`making-a-list`.
================== ============
Name Age
================== ============
John D Hunter 40
Cast of Thousands 41
And Still More 42
================== ============
.. _making-links:
Making links
============
It is easy to make a link to `yahoo <http://yahoo.com>`_ or to some
section inside this document (see :ref:`making-a-table`) or another
document.
You can also reference classes, modules, functions, etc that are
documented using the sphinx `autodoc
<http://sphinx.pocoo.org/ext/autodoc.html>`_ facilites. For example,
see the module :mod:`matplotlib.backend_bases` documentation, or the
class :class:`~matplotlib.backend_bases.LocationEvent`, or the method
:meth:`~matplotlib.backend_bases.FigureCanvasBase.mpl_connect`.
.. _cheatsheet-literal:
This file
=========
.. literalinclude:: cheatsheet.rst
脚注
[1] | 这是一个脚注的内容。 |
[2] | 英文源链接:http://matplotlib.org/sampledoc/cheatsheet.html#making-a-list |
Git操作手册¶
master :默认开发分支
origin :默认远程版本库
创建版本库¶
$ git clone <url> #克隆远程版本库
$ git init #初始化本地版本库
修改和提交¶
$ git status #查看状态
$ git add . #跟踪所有改动过的文件
$ git add <file> #跟踪指定文件
$ git commit -m "commit message" #提交所有更新过的文件
$ git commit --amend #修改最后一次提交
撤销¶
$ git reset --hard HEAD #撤销工作目录中所有未提交文件的修改内容
$ git checkout HEAD <file> #撤销指定的未提交文件的修改内容
$ git revert <commit> #撤销指定提交
分支与标签¶
$ git branch #显示所有本地分支
$ git checkout <branch/tag> #切换到指定分支或者标签
$ git branch <new branch> #创建新分支
$ git branch -d <branch> #删除本地分支
$ git tag #显示所有本地标签
$ git tag <tagname> #基于最新提交创建标签
$ git tag -d <tagname> #删除标签
合并¶
$ git merge <branch> #合并指定分支到当前分支
远程操作¶
$ git remote -V #查看远程仓库版本信息
$ git remote show <remote> #查看指定远程版本库信息
$ git remote add <remote> <url> #添加远程版本库
$ git fetch <remote> #从远程仓库获取代码
$ git pull <remote> <branch> #下载代码及快速合并
$ git push <remote> <branch> #上传代码及快速合并
$ git push --tag #上传所有标签
Git结合坚果云的使用方法¶
1. 将本地的项目仓库进行git初始化
$ git init
2. 将所有目录下所有现有项目文件加入git仓库
$ git add *
3. 查看是否所有文件已经被加入
$ git status
4. 进行第一次提交
$ git commit -m "first commit"
5. 将中央仓库作为自己的远程核心仓库(例:云盘同步文件假为f:\Git_repo\)
$ git remote add origin /f/Git_repo/FORM.git
6. 将远程仓库作为自己的默认推送仓库
$ git push -u origin master
7. java gitignore file
*.class
$ Mobile Tools for Java (J2ME)
.mtj.tmp/
$ Package Files $
*.jar
*.war
*.ear
$ virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
Google身份验证器部署¶
1. 安装¶
1.1 安装依赖软件包¶
yum -y install gcc make pam-devel libpng-devel libtool wget git
1.2 安装Qrencode,谷歌身份验证器需要调用该程序以便终端生成并显示二维码(需要EPEL)¶
yum -y install qrencode
1.3 安装谷歌身份验证器¶
cd ~
git clone https://github.com/google/google-authenticator-libpam.git
cd google-authenticator-libpam/
./bootstrap.sh
./configure
make
sudo make install
1.4 修改/etc/pam.d/sshd第一行后添加谷歌身份验证器PAM模块配置¶
auth required pam_google_authenticator.so
1.5 修改SSH服务配置/etc/ssh/sshd_config¶
ChallengeResponseAuthentication yes
1.6 重启SSH服务¶
RHEL 6/CentOS
service sshd restart
RHEL 7/CentOS 7
systemctl restart sshd.service
1.7 用户设置
运行google-authenticator-libpam目录下的 google-authenticator
二进制文件来创建一个
新的密钥,相关的设置会保存在 ~/.google_authenticator
.
Do you want authentication tokens to be time-based (y/n) y
# 是否使用基于时间方式生成验证口令,注意时间同步
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&...%3Dlocalhost.localdomain
# 显示二维码图片的地址,需要设法能够访问到谷歌,可以使用翻墙,或者寻找暂未被中国长城防火墙屏蔽的谷歌公网IP地址,然后修改系统hosts文件地址映射。
[二维码图片] # 若未安装Qrencode,则不会显示二维码,使用 ``google-authenticator`` 程序扫描二维码。
Your new secret key is: MRQ73VZWQF7Z4EK3GACBAPEH5M
Your verification code is 603335
Your emergency scratch codes are:
60323738
69249157
22062335
85699230
35755622
# 生成的5组应急备用验证码,每个验证码只能使用一次,使用后立即失效。当多次使用手机App端显示的验证码无效时使用,保存备用。
Do you want me to update your "/root/.google_authenticator" file? (y/n) y
# 是否更新配置文件
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y
2. Module options¶
secret=/path/to/secret/file¶
authtok_prompt=prompt¶
Overrides default token prompt. If you want to include spaces in the prompt, wrap the whole argument in square brackets:
auth required pam_google_authenticator.so [authtok_prompt=Your secret token: ]
user=some-user¶
Force the PAM module to switch to a hard-coded user id prior to doing any file operations. Commonly used with secret=.
no_strict_owner¶
DANGEROUS OPTION!
By default the PAM module requires that the secrets file must be owned the user logging in (or if user= is specified, owned by that user). This option disables that check.
This option can be used to allow daemons not running as root to still handle configuration files not owned by that user, for example owned by the users themselves.
allowed_perm=0nnn¶
DANGEROUS OPTION!
By default, the PAM module requires the secrets file to be readable only by the owner of the file (mode 0600 by default). In situations where the module is used in a non-default configuration, an administrator may need more lenient file permissions, or a specific setting for their use case.
debug¶
Enable more verbose log messages in syslog.
try_first_pass / use_first_pass / forward_pass¶
Some PAM clients cannot prompt the user for more than just the password. To work around this problem, this PAM module supports stacking. If you pass the forward_pass option, the pam_google_authenticator module queries the user for both the system password and the verification code in a single prompt. It then forwards the system password to the next PAM module, which will have to be configured with the use_first_pass option.
In turn, pam_google_authenticator module also supports both the standard use_first_pass and try_first_pass options. But most users would not need to set those on the pam_google_authenticator.
noskewadj¶
If you discover that your TOTP code never works, this is most commonly the result of the clock on your server being different from the one on your Android device. The PAM module makes an attempt to compensate for time skew. You can teach it about the amount of skew that you are experiencing, by trying to log it three times in a row. Make sure you always wait 30s (but not longer), so that you get three distinct TOTP codes.
Some administrators prefer that time skew isn’t adjusted automatically, as doing so results in a slightly less secure system configuration. If you want to disable it, you can do so on the module command line:
auth required pam_google_authenticator.so noskewadj
no_increment_hotp¶
Don’t increment the counter for failed HOTP attempts. This is important if log attempts with failed passwords still get an OTP prompt.
nullok¶
Allow users to log in without OTP, if they haven’t set up OTP yet.
echo_verification_code¶
By default, the PAM module does not echo the verification code when it is entered by the user. In some situations, the administrator might prefer a different behavior. Pass the echo_verification_code option to the module in order to enable echoing.
If you would like verification codes that are counter based instead of timebased, use the google-authenticator binary to generate a secret key in your home directory with the proper option. In this mode, clock skew is irrelevant and the window size option now applies to how many codes beyond the current one that would be accepted, to reduce synchronization problems.
3. Encrypted home directories¶
If your system encrypts home directories until after your users entered their password, you either have to re-arrange the entries in the PAM configuration file to decrypt the home directory prior to asking for the OTP code, or you have to store the secret file in a non-standard location:
auth required pam_google_authenticator.so secret=/var/unencrypted-home/${USER}/.google_authenticator
would be a possible choice. Make sure to set appropriate permissions. You also have to tell your users to manually move their .google_authenticator file to this location.
In addition to “${USER}”, the secret= option also recognizes both “~” and ${HOME} as short-hands for the user’s home directory.
When using the secret= option, you might want to also set the user= option. The latter forces the PAM module to switch to a dedicated hard-coded user id prior to doing any file operations. When using the user= option, you must not include “~” or “${HOME}” in the filename.
The user= option can also be useful if you want to authenticate users who do not have traditional UNIX accounts on your system.
CentOS 7安装 freeraidus¶
环境¶
- CentOS 7.0 x86_64
- FreeRadius 3.x
安装¶
1. 安装 freeradius,freeradius-mysql¶
yum install -y freeradius
yum install -y freeradius-mysql
2. 配置 freeraidus 使用mysql认证¶
cd /etc/raddb/mods-enabled
ln -s ../mods-available/sql
修改 /etc/raddb/mods-available/sql
文件
找到 driver = "rlm_sql_null"
修改为 driver = "rlm_sql_mysql"
找到 dialect = "sqlite"
修改为 dialect = "mysql"
保存并退出。
Connection info
下的为数据库信息,去掉 #
,修改信息即可指定数据库。
#. 配置认证客户端
在 /etc/raddb/clients.conf
最后增加一下内容,允许任意ip客户端向radius认证:
client users {
ipaddr = *
secret = testing123
}
- ipadd = *
- 允许所有IP客户端进行认证
- secret = testing123
- 密钥
3. 防火墙开放端口¶
开放udp1812和1813端口(firewalld):
firewall-cmd --zone=public --add-port=1812/udp --permanent
firewall-cmd --zone=public --add-port=1813/udp --permanent
firewall-cmd --reload #重新载入防火墙
防火墙常用命令:
# 添加
firewall-cmd --zone=public --add-port=80/tcp --permanent #(--permanent永久生效,没有此参数重启后失效)
# 重新载入
firewall-cmd --reload
# 查看
firewall-cmd --zone= public --query-port=80/tcp
# 删除
firewall-cmd --zone= public --remove-port=80/tcp --permanent
4. 创建数据库¶
登录数据库服务器:
mysql -uroot -p
Enter password:******
mysql>create database radius;
mysql>grant all on radius.* to radius@localhost identified by "radpass";
mysql>exit;
5. 导入表结构¶
在radius服务器上执行以下命令,或者复制 /etc/raddb/mods-config/sql/main/mysql/scheama.sql
文件到数据库服务器执行。
radius服务器上执行:
mysql -u root -h <数据库IP> radius < /etc/raddb/mods-config/sql/main/mysql/scheama.sql
数据库服务器上执行:
mysql -u root radius <存放路径>/scheama.sql
6. 表结构简要说明¶
表名 | 作用 |
---|---|
radcheck | 用户检查信息表 |
radreply | 用户回复信息表 |
radgroupcheck | 用户组检查信息表 |
radgroupreply | 用户组检查信息表 |
radusergroup | 用户和组关系表 |
radacct | 计费情况表 |
radpostauth | 认证后处理信息,可以包括认证请求成功和拒绝的记录。 |
Django 学习¶
第一课¶
- Django版本:1.11.2
- Pthon版本:3.6.1
安装¶
pip install django
开始¶
创建项目:
django-admin startproject mysite
项目结构:
G:\MYSITE
│ manage.py
│
└─mysite
│ __init__.py
│ urls.py
│ wsgi.py
└─ settings.py
开发服务器(在 manage.py 文件目录下运行):
python manage.py runserver
python manage.py runserver 8080 #8080端口运行
python manage.py runserver 0:8000 #监听所有网卡ip
创建app:
python manage.py startapp polls
app结构:
polls
│ __init__.py
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ urls.py
├─ views.py
│
└─ migrations
__init__.py
写第一个view¶
polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
写url指向这个view
polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
在root URLconf里调用polls.url模块
mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^polls/', include('polls.urls')),
url(r'^admin/', admin.site.urls),
]
注意: include方法的正则表达式不能以 $
结尾。
第二课¶
设置数据库¶
- 在mysite/setting.py中的Databases设置相关参数
支持的数据库
- PostgreSQL,需要 psycopg2,详细参考 PostgreSQL notes
- MySQL,需要 DB API driver 例如:mysqlclient。详情参考 MySQL backend注意事项
- SQLite,参考 SQLite backend注意事项
- Oracle,需要 cx_Oracle,详细参考 Oracle backend注意事项
修改 DATABASE ‘default’ 可以改变数据库的类型。
- ENGINE-支持 ‘django.db.backends.sqlite3’ , ‘django.db.backends.postgresql’ , ‘django.db.backends.mysql’ ,或者 ‘django.db.backends.oracle’
- NAME-数据库名字。
还需要设置:USER, PASSWORD, HOST
- 确保自己的app在 INSTALLED_APPS
初始化数据库表:
$ python manage.py migrate
创建Models¶
在polls应用中创建2个models, Question 和 Choice 。一个 Question 有一个question和一个发布日期。一个 Choice 有两个字段,选择项文本和一个投票计数,每个 Choice 可以关联一个 Question 。
polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
激活Models¶
需要将apps加入到project中来,需要在setting文件中的 INSTALLED_APPS 里指明。这里PollsConfig类是在 polls/apps.py 里,所以路劲是 polls.apps.PollsConfig 。
mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
现在Django知道包含了 polls 应用,运行如下命令:
$ python manage.py makemigrations polls
通过 makemigrations 告诉Django,你已经修改了models。
运行下面的命令能看到models修改的sql过程:
$ python manage.py sqlmigrate polls 0001
Playing with the API¶
使用以下命令进入Django命令行交互模式:
$ python manage.py shell
使用这个命令代替”python”的原因是 manage.py 能设置 DJANGO_SETTING_MODULE 环境变量。
开始探索 database API
# 导入我们刚刚创建的model。
>>> from polls.models import Question, Choice
# 现在还没有Question在我们的数据库里。
>>> Question.objects.all()
<QuerySet []>
# 创建一个新的Question。
# 默认settings文件里已经支持了时区,
# 因此Django希望pub_date是带有时区的时间格式。
# 用timezone.now()代替datetime.datetime.now()
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# 保存这个object进入数据库,你只需使用save()
>>> q.save()
# 现在它有了个ID。注意这里有可能用"1L"来代替"1",这取决于你的正在使用的数据库。
>>> q.id
1
# 通过Python的属性来访问model的字段
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# 通过改变属性来更改值,然后使用save()
>>> q.question_text = "What's up?"
>>> q.save()
# object.all()会显示所有数据库里的数据。
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>
<Question: Question object> 看起来不怎么方便。修改 Question model(在 polls/models.py )并且增加 一个 __str__ 方法就显示的更加友好。
polls/models.py:
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible # only if you need to support Python 2
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
@python_2_unicode_compatible # only if you need to support Python 2
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
这是一个常规的Python方法,我们来自建一个方法
polls/models.py:
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
保存,通过 python manage.py shell 重新打开一个Django命令行:
>>> from polls.models import Question, Choice
# 确认一下__str__()是否工作正常。
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django提供了丰富的数据库查询API,通过关键字来查询。
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# 获取一个今年发布的Question
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# 回应的ID不存在,会抛出一个错误
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# 通过主键来查询是一件平常事,
# 因此Django提供了主键查询的快捷方式
# 下面等价于Question.objects.get(id=1)
>>> Question.objects.get(pk=1)
<Question: What's up?>
# 确认一下自定义方法是否工作正常
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
# TODO: 这段不是很理解。
>>> q = Question.objects.get(pk=1)
# 显示所有相关的Choices
>>> q.choice_set.all()
<QuerySet []>
# 新建3个Choices
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice object可以通过API来访问与它关联的Question objects
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()