Django_Models

Django 的 ORM 有多种关系:一对一,多对一,多对多。

各自定义的方式为 :

  • OneToOneField

一对一,一个有一个,即 has one:

  • ForeignKey,

多个属于一个, lots of A belong to B
一个有很多个, has many: B has many A
在建立 ForeignKey 时,另一个表会自动建立对应的关系

  • ManyToManyField

多对多,一个既有很多个,又属于很多个,即 has many, belong to Many
在建立ManyToManyField时,另一个表会自动建立对应的关系

OneToOneField Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from django.db import models
class Engine(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=25)
# 这个车的引擎的name可以在表Engine的name中找到,同时也能从引擎的name找到这两车
engine = models.OneToOneField(Engine)
def __unicode__(self):
return self.name
>>> from testapp.models import Car, Engine
>>> e = Engine.objects.get(name='Diesel')
# Engine 的model 定义中并没有car,这个是自动生成的,**用关联表的类名小写直接访问**
>>> e.car
<Car: Audi> # 返回的使用一个可调用的对象
>>> c = Car.objects.get(name='Audi')

ForeignKey with unique=True Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Engine2(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car2(models.Model):
name = models.CharField(max_length=25)
# 这个车的引擎的name可以在Engine2中name找到,同时Engine2的引擎有很多车用
engine = models.ForeignKey(Engine2, unique=True)
def __unicode__(self):
>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
# 用了这个引擎的所有车
>>> e2.car2_set.all()
[<Car2: Mazda>] # 处理的是QuerySet而不是模型实例
# 在未定义的model中用关联表类名小写加"_set"来访问,这里是car2_set,多对多也一样
# Engine2 的model 定义中并没有car2,这个是自动生成的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
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()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
# 一本书有很多作者,一个作者也可能有很多书
authors = models.ManyToManyField(Author)
# 一本书属于出版社,一个出版社可以出很多书
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
上面定义了Publisher,Author,Book三个类,按照“每个数据库表对应一个类”的“原则”,执行python manage.py syncdb 应该创建三个表,但你可以看到(创建的时候就有打印显示)数据库里多了一个表(四个表)名为:book_authors ,这就是那个“额外的表”,是因为“多对多”字段的原因创建的。
Chai 2014-02-07 16:21:57
多对多关系是没法用字段来表示的,需要用额外的一张表来维护多对多关系。
------
表内字段
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
-------
外键,一对多(多对一)
从belong to 的关系来看
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
从has many 的关系来看
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
实际上,book_set 只是一个 QuerySet,所以它可以像QuerySet一样,能实现数据过滤和分切,例如:
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]
属性名称book_set是由模型名称的小写(如book)加_set组成的。
------
多对多
>>> b = Book.objects.get(id=50)
书籍的所有作者
>>> b.authors.all()
[<Author: Adrian Holovaty>, <Author: Jacob Kaplan-Moss>]
>>> b.authors.filter(first_name='Adrian')
[<Author: Adrian Holovaty>]
>>> b.authors.filter(first_name='Adam')
反向查询也可以。
作者的所有书
>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]

其他:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Python3兼容Python2
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Article(models.Model):
title = models.CharField('标题', max_length=256)
content = models.TextField('内容')
pub_date = models.DateTimeField('发表时间', auto_now_add=True, editable = True)
update_time = models.DateTimeField('更新时间',auto_now=True, null=True)
def __str__(self):
return self.title

python之@property,@staticmethod,@classmethod

#coding=utf-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class MyClass(object):
def __init__(self):
print 'init'
self._name = 'the5fire'
@staticmethod
def static_method():
print 'This is a static method!'
@classmethod
def class_method(cls):
print 'This is a class method',cls
print 'visit the property of the class:',cls.name
print 'visit the static method of the class:',cls.static_method()
instance = cls()
print 'visit the normal method of the class:',instance.test()
def test(self):
print 'call test'
@property
def name(self):
return self._name
if __name__ == '__main__':
MyClass.static_method()
MyClass.class_method()
mc = MyClass()
print mc.name
mc.name = 'huyang'

Curl vs Wget

共性

都是可以从FTP、HTTP、HTTPS下载内容的命令行工具
都可以发送HTTP POST请求
都支持HTTP cookies
都被设计为工作中无需用户干涉——像内置脚本一样
都是完全开源免费的
都是90年代的项目
都支持metalink

差异

curl:

库。curl由libcurl——一个API稳定且使用自由的跨平台库技术支持。这个主要的差别使二者产生了完全不同的内部体系。当然制作库也是比一个“单纯的”命令行工具要稍微难一点的。
管道。curl工作起来更像是传统unix的cat命令,基于“万事无不管道”的态度它向stdout发送更多信息,从stdin读取更多。Wget类比起来则更像cp命令。
单次性。curl本质上是做单次数据转移的。它只转移用户指定的URLs,并不包括任何递归的下载逻辑或是各种HTML的解析器。
更多的协议。curl支持FTP、FTPS、Gopher、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS、FILE、POP3、IMAP、SMB/CIFS、SMTP、RTMP和RTSP。Wget仅支持HTTP、HTTPS和FTP。
更轻便。相比wget,curl可构建和运行在更多平台上。举个栗子:OS/400,TPS和其他非直系unix拷贝的“外来”平台。
更多的SSL库和SSL支持。curl可以用11种(11种!)不同的SSL/TLS库来构建,并且为协议细节提供了更多控制权和尽可能的支持。
HTTP认证。curl支持更多HTTP认证的方法,尤其是HTTP代理:Basic、Digest、NTLM和Negotiate。
SOCKS。curl支持好几个版本SOCKS协议的代理访问。
双向性。curl可以提供上传和发送的能力。Wget只能提供简单的HTTP POST支持。
HTTP多部分/格式数据的发送,这允许用户在一般的模拟浏览器中进行HTTP“上传”以及进行HTTP自动化来扩展内容。
curl支持gzip以及压缩内容编码,并且会自动解压。
curl提供并且压缩传输编码的HTTP,wget则不。
curl支持HTTP/2并且使用Happy Eyeballs[1]进行双栈连接。
更活跃的开发者。这可能会引发讨论,我基于如下三点考虑:邮件列表活跃度、源代码提交频次以及发布频次。任何跟进这两个项目的人都可以注意到curl在这三点均有着更高的数据,并且已经保持了10年以上。在openhub上比较
Wget

Wget仅仅是命令行工具而非库。
递归性!Wget相对于curl而言主要的强势之处在于它可以递归下载,或是下载在远程资源中提到的任何资源,无论是一个HTML页面还是一个FTP目录列表。
更老的资历。Wget可以追溯的1995年,而curl不会早于1996年末。
GPL。Wget是GPL第三版协议。curl是MIT许可。
GNU。Wget是GNU计划的一部分,版权指定为FSF。curl项目则完全独立并且脱离于任何父级组织,几乎所有版权被Daniel所有。
Wget不需要额外的指令选项去下载远程的URL至本地文件,curl需要 -o或者 -O。
Wget的SSL/TLS支持仅有GnuTLS或者OpenSSL。
Wget仅支持Basic认证作为唯一的HTTP代理。
Wget没有SOCKS支持。
可以从提前中断的传输中回复并且继续下载,curl则没有对应的功能。
Wget默认开启更多设置:cookies、重定向跟随、远程资源的时间戳等。curl的大多数这些设置需要单独开启。
Wget四个字母在传统键盘上仅用左手就能输入!

转于 http://www.cnblogs.com/mangi/p/5584838.html

Docker命令

Docker 是实现轻量级的操作系统虚拟化解决方案。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

基本概念

Docker 包括三个基本概念

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

镜像: 是一个只读的模板。可创建,可删除,可修改,可共享.

容器: 是从镜像创建的运行实例。每个容器都是相互隔离的、保证安全的平台。启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。

仓库: 是集中存放镜像文件的场所。

仓库注册服务器上存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

镜像有点像面向对象里的类,容器则是对应的一个实例,仓库是保存类的文件(类有不同的版本),仓库注册服务器是文件所在的计算机.

最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。

安装

更新源
sudo apt-get update

通过apt命令在线安装docker
sudo apt-get install docker-engine

开启docker的守护进程(Docker服务开启)
sudo service docker start

国际惯例,用一个Hello world的来测试安装成功
sudo docker run hello-world

更新Docker
sudo apt-get upgrade docker-engine

卸载Docker
sudo apt-get purge docker-engine
sudo rm -rf /var/lib/docker

创建Docker用户组,避免使用sudo
sudo usermod -aG docker user_name

镜像管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
搜索docker.hub中的镜像,无需登录
docker search xxxx
sudo docker pull ubuntu:16.04
若不使用:tags那么tags默认为latest
docker images:
列出本地所有镜像
docker search <IMAGE_ID/NAME>:
查找image
docker pull <IMAGE_ID>
下载image
docker push <IMAGE_ID>
上传image
docker rmi <IMAGE_ID>
删除image, 注意 docker rm 命令是移除容器。
sudo docker save -o XXXXXX.tar <image_id>
保存镜像
docker load --input XXXXXX.tar
载入镜像

镜像使用
http://wiki.jikexueyuan.com/project/docker-technology-and-combat/create.html
http://www.runoob.com/docker/docker-image-usage.html

容器使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
查看:
docker ps
-a:同时显示停止的容器,默认只显示启动状态
-q:只显示容器id
------
使用:
docker start <CONTAINER_ID>:重新启动container
docker attach <CONTAINER_ID> 连接到启动的容器
要先启动,才能连接
docker stop <CONTAINER_ID>:停止container
------
监测:
docker inspect <CONTAINER_ID> 容器底层信息
docker top <CONTAINER_ID>成 容器进程信息
docker logs <CONTAINER_ID> : 输出容器日志
docker logs -f <CONTAINER_ID> : 实时输出容器日志
------
导入导出:
docker export <CONTAINER_ID> > xxxx.tar 导出容器
cat xxxx.tar | sudo docker import - ubuntu:v1.0 从容器快照导出为镜像
-----

如下

1
2
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker rm <CONTAINER_ID>:删除container ,如果要删除一个运行中的容器,可以添加 -f 参数。
docker rm `docker ps -a -q`:删除所有容器
docker cp <CONTAINER_ID>:path hostpath:复制容器内的文件到宿主机目录上
docker kill `docker ps -q`
docker rmi `docker images -q -a`
docker wait <CONTAINER_ID>:阻塞对容器的其他调用方法,直到容器停止后退出
docker top <CONTAINER_ID>:查看容器中运行的进程
docker diff <CONTAINER_ID>:查看容器中的变化
docker inspect <CONTAINER_ID>:查看容器详细信息(输出为Json)
-f:查找特定信息,如docker inspect -f '{{ .NetworkSettings.IPAddress }}'
docker commit -m "comment" -a "author" <CONTAINER_ID> ouruser/imagename:tag
docker extc -it <CONTAINER> <COMMAND>:在容器里执行命令,并输出结果

容器管理

1
2
3
4
5
6
7
8
docker run <IMAGE_ID>
-i:标准输入给容器
-t:分配一个虚拟终端
否则这样使用 docker run ubuntu:14.04 /bin/echo 'Hello world'
-d:以守护进程方式运行(后台)
--name: 指定容器的名称
--rm:退出时删除容器

docker run –name ovcer_the_container -i -t ubuntu /bin/bash
root@1ce9f640478d:/#

1
上面的命令将会创建一个名为ovcer_the_container的容器。对于一个合法的容器的名称来说只可以包括以下字符:小写字母a~z、大写字母A-Z、数字09、下划线、圆点、横线。

## 网络相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
默认匹配docker容器的5000端口号随机分配端口号
-P
查看容器的5000端口对应本地机器的IP和端口号,也可docker ps直接查看
docker port <CONTAINER_ID> 5000
指定端口号
-p <HOT_PORT>:<CONTAINER_PORT>
绑定主机的特定接口的端口号
docker run -p 127.0.0.1:5000:5000
绑定特定端口号(主机的所有网络接口的5000端口均绑定容器的5000端口)
docker run -p 5000:5000
绑定udp端口号
docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py:
查看映射端口配置
$docker port nostalgic_morse 5000
127.0.0.1:49155.

数据管理

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像

可以在容器启动的时候添加-v参数指定容器卷,也可以在Dockerfile里用VOLUMN命令添加

创建一个数据卷

在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。
下面创建一个 web 容器,并加载一个数据卷到容器的 /webapp 目录。
sudo docker run -d -P –name web -v /webapp training/webapp python app.py
注意:也可以在 Dockerfile 中使用 VOLUME 来添加一个或者多个新的卷到由该镜像创建的任意容器。

## 挂载一个本地目录作为数据卷

sudo docker run -d -P –name web -v /src/webapp:/opt/webapp training/webapp python app.py
上面的命令加载主机的 /src/webapp 目录到容器的 /opt/webapp 目录。

挂载一个本地文件作为数据卷

sudo docker run -it -v ~/.bash_history:/.bash_history
这样就可以记录在容器输入过的命令了。

共享

在一个容器创建容器卷后,其他容器便可以通过–volumes-from共享这个容器卷数据,如下:

  1. docker run -d -v /dbdata –name db1 training/postgres echo Data-only container for postgres
    首先启动了一个d1容器,并为它增加一个数据卷/dbdata,然后启动另一个容器,共享这个数据卷

  2. docker run -d –volumes-from db1 –name db2 training/postgres

此时容器db2使用了db1的容器卷,当容器db1被删除时,容器卷也不会被删除,只有所有容器不再使用此容器卷时,才会被删除
docker rm -v:删除容器卷

备份与恢复

备份

首先使用 –volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:
$ sudo docker run –volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
tar 命令来将 dbdata 卷备份为本地的 /backup/backup.tar。

恢复

如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 dbdata2。
$ sudo docker run -v /dbdata –name dbdata2 ubuntu /bin/bash
然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar 解压备份文件到挂载的容器卷中。
$ sudo docker run –volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

仓库管理

docker login:登录
本地用户目录的 .dockercfg 中将保存用户的认证信息。

http://www.myexception.cn/cloud/1787029.html

脚手架

Docker Compose

允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。
http://wiki.jikexueyuan.com/project/docker-technology-and-combat/fintro.html

Docker Machine

Docker Machine是一个简化安装Docker环境的工具。市场上主流Linux系统版本很多,使用Machine工具就简单很多,一两条命令即可在主流Linux系统上安装Docker环境,用户不用考虑什么操作系统。Docker Machine还具备Docker工具管理虚拟化技术,Generic驱动默认管理LXC容器技术。
http://chuansong.me/n/341280351544

https://yeasy.gitbooks.io/docker_practice

Git忽略文件不加入版本控制

共享式忽略

可以被git clone,只是是不在版本库里,比如说一些IDE的配置如果没有被.gitignore,可能会被别人merge什么的
新建 .gitignore 文件,放在工程目录任意位置即可。.gitignore 文件可以忽略自己
.gitignore文件可以被提交到共享库中被协作者共享

独享式忽略

文件彻底被排除,不会被版本控制,也不会被推送
.git/info/exclude

全局.gitignore

git 提供了一个全局的 .gitignore,你可以在你的用户目录下创建 ~/.gitignoreglobal 文件,以同样的规则来划定哪些文件是不需要版本控制的。
需要执行 git config –global core.excludesfile ~/.gitignoreglobal来使得它生效。

注意:
忽略的文件,只针对未跟踪文件有效,对已加入版本库的文件无效。要先 git rm -r —cached ignore_file`

.gitignore文件语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# #此为注释 – 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但lib.a 除外
build/ # 忽略 build/整个build目录,但不包括同名文件,若想保留build空文件夹,改下方法,在build下也加一个.gitignore,内容为*!.gitignore
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
其他的一些过滤条件
* ?:代表任意的一个字符
* *:代表任意数目的字符
* {!ab}:必须不是此类型
* {ab,bb,cx}:代表ab,bb,cx中任一类型即可
* [abc]:代表a,b,c中任一字符即可
* [ ^abc]:代表必须不是a,b,c中任一字符

若test下有多个文件和文件夹。若要ignore某些文件夹,应该这个配置.gitignore文件。若test下有test1,test2,test3文件。要track test3,则.gitignore文件为:
test/test1
test/test2
!test/test3
若为:
test/
!test/test3 ,则不能track test3。


gitignore 还有个有意思的小功能, 一个空的 .gitignore 文件 可以当作是一个 placeholder 。当你需要为项目创建一个空的 log 目录时, 这就变的很有用。 你可以创建一个 log 目录 在里面放置一个空的 .gitignore 文件。这样当你 clone 这个 repo 的时候 git 会自动的创建好一个空的 log 目录了。—

.gitignore文件参考

Python.gitignore
https://github.com/github/gitignore/blob/master/Python.gitignore