2017年3月

Debian7下iptables初始化默认规则

参考官方文档:https://wiki.debian.org/iptables

先查看当前规则:iptables -L

默认规则如下时表示当前规则为空

Chain INPUT (policy ACCEPT)
 target     prot opt source               destination

 Chain FORWARD (policy ACCEPT)
 target     prot opt source               destination

 Chain OUTPUT (policy ACCEPT)
 target     prot opt source               destination


创建一个iptables规则文件并写入:

nano /etc/iptables.test.rules
写入:

*filter

# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allows all outbound traffic
# You could modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allows SSH connections 
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Now you should read up on iptables rules and consider whether ssh access 
# for everyone is really desired. Most likely you will only allow access from certain IPs.

# Allow ping
#  note that blocking other types of icmp packets is considered a bad idea by some
#  remove -m icmp --icmp-type 8 from this line to allow all kinds of icmp:
#  https://security.stackexchange.com/questions/22711
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

保存退出后,使规则生效

 iptables-restore < /etc/iptables.test.rules

当出现类似如下错误
iptables-restore v1.4.14: no command specified
Error occurred at line: 38
Try `iptables-restore -h' or 'iptables-restore --help' for more information.

则是文档格式问题,将文档格式转换为unix格式,再直接导入到Debian中

查看规则
iptables -L

iptables-save > /etc/iptables.up.rules

生效后编辑

nano /etc/network/if-pre-up.d/iptables

加入

#!/bin/sh
 /sbin/iptables-restore < /etc/iptables.up.rules

保存退出

chmod +x /etc/network/if-pre-up.d/iptables

重启即可

YII事务操作,抛出异常及回滚操作

一:DAO 使用事务

当一个应用要执行几条查询,每条查询要从数据库中读取并/或向数据库中写入信息时, 保证数据库没有留下几条查询而只执行了另外几条查询是非常重要的。 事务,在 Yii 中表现为 CDbTransaction 实例,可能会在下面的情况中启动:

 

  • 开始事务.
  • 一个个执行查询。任何对数据库的更新对外界不可见。
  • 提交事务。如果事务成功,更新变为可见。
  • 如果查询中的一个失败,整个事务回滚。

 

上述工作流可以通过如下代码实现:

 

$transaction=$connection->beginTransaction();   //开始事务

try {

foreach($sqls as $sql){

if( !$connection->createCommand($sql)->execute() ){

throw new Exception();

}

}

//.... other SQL executions

$transaction->commit();//提交事务

} catch(Exception $e) // 如果有一条查询失败,则会抛出异常 {

$transaction->rollBack();//事务回滚

//  $apply_arr['errorCode'] = '106';  //数据添加/更新失败
//  $apply_arr['data']['reason'] = $e->getMessage();
//  或 echo  $e->getMessage();

}

 

二. 使用 AR 处理事务

每个 AR 实例都含有一个属性名叫 dbConnection ,是一个 CDbConnection 的实例,这样我们可以在需要时配合 AR 使用由 Yii DAO 提供的 事务 功能:

 

$transaction=Yii::app()->db->beginTransaction();
try{
    foreach ($models as $model) {
        if (!$model->save()) {
            throw new Exception();
        }
    }
    $transaction->commit();
} catch(Exception $e){
    $transaction->rollBack();
}

 

注意:

1:上面开始事务中:红色部分其实都是CDbconnection的实例,

即可以用这种写法:$transaction = Yii::app()->db->beginTransaction();

Django模板系统(非常详细)

 

原文:http://blog.csdn.net/zhangxinrun/article/details/8095118/

前面的章节我们看到如何在视图中返回HTML,但是HTML是硬编码在Python代码中的
这会导致几个问题:
1,显然,任何页面的改动会牵扯到Python代码的改动
网站的设计改动会比Python代码改动更频繁,所以如果我们将两者分离开会更方便
2,其次,写后台Python代码与设计HTML是不同的工作,更专业的Web开发应该将两者分开
页面设计者和HTML/CSS程序员不应该编辑Python代码,他们应该与HTML打交道
3,程序员写Python代码同时页面设计者写HTML模板会更高效,而不是一个人等待另一个人编辑同样的文件
因此,使用Django的模板系统分离设计和Python代码会更干净更易维护

模板系统基础
Django模板是一个string文本,它用来分离一个文档的展现和数据
模板定义了placeholder和表示多种逻辑的tags来规定文档如何展现
通常模板用来输出HTML,但是Django模板也能生成其它基于文本的形式
让我们来看看一个简单的模板例子:

  1. <html>
  2. <head><title>Ordering notice</title></head>
  3. <body>
  4. <p>Dear {{ person_name }},</p>
  5. <p>Thanks for placing an order from {{ company }}. It's scheduled to
  6. ship on {{ ship_date|date:"F j, Y" }}.</p>
  7. <p>Here are the items you've ordered:</p>
  8. <ul>
  9. {% for item in item_list %}
  10. <li>{{ item }}</li>
  11. {% endfor %}
  12. </ul>
  13. {% if ordered_warranty %}
  14. <p>Your warranty information will be included in the packaging.</p>
  15. {% endif %}
  16. <p>Sincerely,<br />{{ company }}</p>
  17. </body>
  18. </html>

这个模板本质上是HTML,但是夹杂了一些变量和模板标签:
1,用{{}}包围的是变量,如{{person_name}},这表示把给定变量的值插入,如何指定这些变量的值我们即将说明
2,用{%%}包围的是块标签,如{%if ordered_warranty%}
块标签的含义很丰富,它告诉模板系统做一些事情
在这个例子模板中包含两个块标签:for标签表现为一个简单的循环结构,让你按顺序遍历每条数据
if标签则表现为逻辑的if语句
在这里,上面的标签检查ordered_warranty变量的值是否为True
如果是True,模板系统会显示{%if ordered_warranty%}和{%endif%}之间的内容
否则,模板系统不会显示这些内容
模板系统也支持{%else%}等其它逻辑语句
3,上面还有一个过滤器的例子,过滤器是改变变量显示的方式
上面的例子中{{ship_date|date:"F j, Y"}}把ship_date变量传递给过滤器
并给date过滤器传递了一个参数“F j, Y”,date过滤器以给定参数的形式格式化日期
类似于Unix,过滤器使用管道字符“|”
Django模板支持多种内建的块标签,并且你可以写你自己的标签

使用模板系统
在Python代码中使用模板系统,请按照下面的步骤:
1,用模板代码创建一个Template对象
Django也提供指定模板文件路径的方式创建Template对象
2,使用一些给定变量context调用Template对象的render()方法
这将返回一个完全渲染的模板,它是一个string,其中所有的变量和块标签都会根据context得到值

创建模板对象
最简单的方式是直接初始化它,Template类在django.template模块中,初始化方法需要一个参数
下面进入Python交互环境看看:

  1. >>> from django.template import Template
  2. >>> t = Template("My name is {{my_name}}.")
  3. >>> print t

你将看到如下信息

  1. <django.template.Template object at 0xb7d5f24c>

0xb7d5f24c每次都会改变,但是无所谓,它是Template对象的Python“identity”
在这本书中,我们会在Python的交互式会话环境中展示一些示例。当你看到三个大于号'>>>',就可以确定是在交互环境中了。
如果你从本书中拷贝代码,记得不要拷贝这些大于号。
当你创建Template对象,模板系统会编译模板代码,并准备渲染
如果你的模板代码有语法错误,调用Template()方法会触发TemplateSyntaxError异常

  1. >>> from django.template import Template
  2. >>> t = Template('{%notatag%}')
  3. Traceback (most recent call last):
  4.     File "<stdin>", line 1, in ?
  5.     ...
  6.    django.template.TemplateSyntaxError: Invalid block tag: 'notatag'

系统触发TemplateSyntaxError异常可能出于以下情况:
1,不合法的块标签
2,合法块标签接受不合法的参数
3,不合法的过滤器
4,合法过滤器接受不合法的参数
5,不合法的模板语法
6,块标签没关

渲染模板
一旦你拥有一个Template对象,你可以通过给一个context来给它传递数据
context是一个变量及赋予的值的集合,模板使用它来得到变量的值,或者对于块标签求值
这个context由django.template模块的Context类表示
它的初始化函数有一个可选的参数:一个映射变量名和变量值的字典
通过context调用Template对象的render()方法来填充模板,例如:

  1. >>> from django.template import Context, Template
  2. >>> t = Template("My name is {{name}}.")
  3. >>> c = Context({"name""Stephane"})
  4. >>> t.render(c)
  5. 'My name is Stephane.'

变量名必须以字母(A-Z或a-z)开始,可以包含数字,下划线和小数点,变量名大小写敏感
下面是一个模板编译和渲染的例子,使用这章开始时的模板例子:

  1. >>> from django.template import Template, Context
  2. >>> raw_template = """<p>Dear {{ person_name }},</p>
  3. ...
  4. ... <p>Thanks for ordering {{ product }} from {{ company }}. It's scheduled to
  5. ... ship on {{ ship_date|date:"F j, Y" }}.</p>
  6. ...
  7. ... {% if ordered_warranty %}
  8. ... <p>Your warranty information will be included in the packaging.</p>
  9. ... {% endif %}
  10. ...
  11. ... <p>Sincerely,<br />{{ company }}</p>"""
  12. >>> t = Template(raw_template)
  13. >>> import datetime
  14. >>> c = Context({'person_name''John Smith',
  15. ...     'product''Super Lawn Mower',
  16. ...     'company''Outdoor Equipment',
  17. ...     'ship_date': datetime.date(200942),
  18. ...     'ordered_warranty': True})
  19. >>> t.render(c)
  20. "<p>Dear John Smith,</p>\n\n<p>Thanks for ordering Super Lawn Mower from Outdoor Equipment.
  21. It's scheduled to ship on April 22009.</p>\n\n<p>Your warranty information will be included
  22. in the packaging.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment</p>"

让我们来看看都做了些什么:
1,我们import Template和Context类,它们都在django.template模块里面
2,我们把模板文本存储在raw_template变量里,我们使用"""来构建string,它可以跨越多行
3,我们创建模板对象t,并给Template类的初始化函数传递raw_template变量
4,我们从Python的标准库import datetime模块,下面会用到它
5,我们创建一个context对象c,它的初始化函数使用一个映射变量名和变量值的字典
例如我们指定person_name的值为'John Smith',product的值为'Super Lawn Mower'等等
6,最后,我们调用模板对象的render()方法,参数为context对象c
这将返回渲染后的模板,将模板中的变量值替换并计算块标签的结果
如果你刚接触Python,你可能会问为什么输出中包含了新行字符'\n'而不是换行
这是因为Python交互环境中调用t.render(c)会显示string的representation而不是string的值
如果你想看到换行而不是'\n',使用print t.render(c)即可
上面是使用Django模板系统的基础,只是创建一个模板对象和context对象然后调用render()方法
同一个模板,多个context的情况:
一旦你创建了一个模板对象,你可以渲染多个context,例如:

  1. >>> from django.template import Template, Context
  2. >>> t = Template('Hello, {{ name }}')
  3. >>> print t.render(Context({'name''John'}))
  4. Hello, John
  5. >>> print t.render(Context({'name''Julie'}))
  6. Hello, Julie
  7. >>> print t.render(Context({'name''Pat'}))
  8. Hello, Pat

无论何时,你使用同一个模板来渲染多个context的话,创建一次Template对象然后调用render()多次会更高效

  1. # Bad
  2. for name in ('John''Julie''Pat'):
  3.     t = Template('Hello, {{ name }}')
  4.     print t.render(Context({'name': name}))
  5. # Good
  6. t = Template('Hello, {{ name }}')
  7. for name in ('John''Julie''Pat'):
  8.     print t.render(Context({'name': name}))

Django的模板解析非常快,在后台,大部分的解析通过一个单独的对正则表达式的调用来做
这与基于XML的模板引擎形成鲜明对比,XML解析器比Django的模板渲染系统慢很多

Context变量查找
上面的例子中,我们给模板context传递了简单的值,大部分是string,以及一个datetime.date
尽管如此,模板系统优雅的处理更复杂的数据结构,如列表,字典和自定义对象
在Django模板系统中处理复杂数据结构的关键是使用(.)字符
使用小数点来得到字典的key,属性,对象的索引和方法
下面通过例子来解释,通过(.)访问字典的key:

  1. >>> from django.template import Template, Context
  2. >>> person = {'name''Sally''age''43'}
  3. >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
  4. >>> c= Context({'person': person})
  5. >>> t.render(c)
  6. 'Sally is 43 years old.'

通过(.)来访问对象的属性:

  1. >>> from django.template import Template, Context
  2. >>> import datetime
  3. >>> d = datetime.date(199352)
  4. >>> d.year
  5. 1993
  6. >>> d.month
  7. 5
  8. >>> d.day
  9. 2
  10. >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
  11. >>> c = Context({'date': d})
  12. >>> t.render(c)
  13. 'The month is 5 and the year is 1993.'

下面的例子使用一个自定义类:

  1. >>> from django.template import Template, Context
  2. >>> class Person(object):
  3. ...    def __init__(self, first_name, last_name):
  4. ...        self.first_name, self.last_name = first_name, last_name
  5. >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
  6. >>> c = Context({'person': Person('John''Smith')})
  7. >>> t.render(c)
  8. 'Hello, John Smith.'

小数点也可以用来调用列表的索引:

  1. >>> from django.template import Template, Context
  2. >>> t = Template('Item 2 is {{ items.2 }}.')
  3. >>> c = Contexst({'items': ['apples''bananas''carrots']})
  4. >>> t.render(c)
  5. 'Item 2 is carrots.'

负数的列表索引是不允许的,例如模板变量{{ items.-1 }}将触发TemplateSyntaxError
最后小数点还可以用来访问对象的方法,例如Python的string有upper()和isdigit()方法:

  1. >>> from django.template import Template, Context
  2. >>> t = Template('{{ var }} -- {{var.upper }} -- {{ var.isdigit }}')
  3. >>> t.render(Context({'var''hello'}))
  4. 'hello -- HELLO -- False'
  5. >>> t.render(Context({'var''123'}))
  6. '123 - 123 - True'

注意,调用方法时你不能加括号,你也不能给方法传递参数
你只能调用没有参数的方法,后面我们会解释这些
总结一下,当模板系统遇到变量名里有小数点时会按以下顺序查找:
1,字典查找,如foo["bar"]
2,属性查找,如foo.bar
3,方法调用,如foo.bar()
3,列表的索引查找,如foo[bar]
小数点可以多级纵深查询,例如{{ person.name.upper }}表示字典查询person['name']然后调用upper()方法

  1. >>> from django.template import Template, Context
  2. >>> person = {'name''Sally''age''43'}
  3. >>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')
  4. >>> c = Context({'person': person})
  5. >>> t.render(c)
  6. 'SALLY is 43 years old.'

关于方法调用
方法调用要比其他的查询稍微复杂一点,下面是需要记住的几点:
1,在方法查询的时候,如果一个方法触发了异常,这个异常会传递从而导致渲染失
败,但是如果异常有一个值为True的silent_variable_failure属性,这个变量会渲染成空string:

  1. >>> t = Template("My name is {{ person.first_name }}.")
  2. >>> class PersonClas3:
  3. ...     def first_name(self):
  4. ...         raise AssertionError, "foo"
  5. >>> p = PersonClass3()
  6. >>> t.render(Context({"person": p}))
  7. Traceback (most recent call last):
  8. ...
  9. AssertionError: foo
  10. >>> class SilentAssetionError(AssertionError):
  11. ...     silent_variable_failure = True
  12. >>> class PersonClass4:
  13. ...     def first_name(self):
  14. ...         raise SilentAssertionError
  15. >>> p = PersonClass4()
  16. >>> t.render(Context({"person": p}))
  17. "My name is ."

2,方法调用仅仅在它没有参数时起作用,否则系统将继续查找下一个类型(列表索引查询)
3,显然一些方法有副作用,让系统访问它们是很愚蠢的,而且很可能会造成安全性问
题。
例如你有一个BankAccount对象,该对象有一个delete()方法,模板系统不应该允许做下面的事情
I will now delete this valuable data. {{ account.delete }}
为了防止这种状况,可以在方法里设置一个方法属性alters_data
如果设置了alters_data=True的话模板系统就不会执行这个方法:

  1. def delete(self):
  2.     # Delete the account
  3. delete.alters_data = True

不合法的变量怎样处理
默认情况下如果变量不存在,模板系统会把它渲染成空string,例如:

  1. >>> from django.template import Template, Context
  2. >>> t = Template('Your name is {{ name }}.')
  3. >>> t.render(Context())
  4. 'Your name is .'
  5. >>> t.render(Context({'var''hello'}))
  6. 'Your name is .'
  7. >>> t.render(Context({'NAME''hello'}))
  8. 'Your name is .'
  9. >>> t.render(Context({'Name''hello'}))
  10. 'Your name is .'

系统会静悄悄地显示错误的页面,而不是产生一个异常,因为这种情况通常是人为的错误。
在现实情形下,一个web站点因为一个模板代码语法的错误而变得不可用是不可接受的。
我们可以通过设置Django配置更改Django的缺省行为,第10章扩展模板引擎会我们会讨论这个

玩玩Context对象
大多数情况下你初始化Context对象会传递一个字典给Context()
一旦你初始化了Context,你可以使用标准Python字典语法增减Context对象的items:

  1. >>> from django.template import Context
  2. >>> c = Context({"foo""bar"})
  3. >>> c['foo']
  4. 'bar'
  5. >>> del c['foo']
  6. >>> c['foo']
  7. ''
  8. >>> c['newvariable'] = 'hello'
  9. >>> c['newvariable']
  10. 'hello'

Context对象是一个stack,你可以push()和pop()
如果你pop()的太多的话它将触发django.template.ContextPopException:

  1. >>> c = Context()
  2. >>> c['foo'] = 'first level'
  3. >>> c.push()
  4. >>> c['foo'] = 'second level'
  5. >>> c['foo']
  6. 'second level'
  7. >>> c.pop()
  8. >>> c['foo']
  9. 'first level'
  10. >>> c['foo'] = 'overwritten'
  11. >>> c['foo']
  12. 'overwritten'
  13. >>> c.pop()
  14. Traceback (most recent call last):
  15. ...
  16. django.template.ContextPopException

第10章你会看到使用Context作为stack自定义模板标签

模板标签和过滤器基础
我们已经提到模板系统使用内建的标签和过滤器
这里我们看看常见的,附录6包含了完整的内建标签和过滤器,你自己熟悉那个列表来了解可以做什么是个好主意

if/else
{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值
系统则会显示{% if %}和{% endif %}间的所有内容:

  1. {% if today_is_weekend %}
  2.     <p>Welcome to the weekend!</p>
  3. {% else %}
  4.     <p>Get back to work.</p>
  5. {% endif %}

{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:

  1. {% if athlete_list and coach_list %}
  2.     Both athletes and coaches are available.
  3. {% endif %}
  4. {% if not athlete_list %}
  5.     There are no athletes.
  6. {% endif %}
  7. {% if athlete_list or coach_list %}
  8.     There are some athletes or some coaches.
  9. {% endif %}
  10. {% if not athlete_list or coach_list %}
  11.     There are no athletes or there are some coaches.
  12. {% endif %}
  13. {% if athlete_list and not coach_list %}
  14.     There are some athletes and absolutely no coaches.
  15. {% endif %}

{% if %}标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

  1. {% if athlete_list and coach_list or cheerleader_list %}

如果你想结合and和or来做高级逻辑,只需使用嵌套的{% if %}标签即可:

  1. {% if athlete_list %}
  2.     {% if coach_list or cheerleader_list %}
  3.         We have athletes, and either coaches or cheerleaders!
  4.     {% endif %}
  5. {% endif %}

多次使用同一个逻辑符号是合法的:

  1. {% if athlete_list or coach_list or parent_list or teacher_list %}

没有{% elif %}标签,使用嵌套的{% if %}标签可以做到同样的事情:

  1. {% if athlete_list %}
  2.     <p>Here are the athletes: {{ athlete_list }}.</p>
  3. {% else %}
  4.     <p>No athletes are available.</p>
  5.     {% if coach_list %}
  6.         <p>Here are the coaches: {{ coach_list }}.</p>
  7.     {% endif %}
  8. {% endif %}

确认使用{% endif %}来关闭{% if %}标签,否则Django触发TemplateSyntaxError

for
{% for %}标签允许你按顺序遍历一个序列中的各个元素
Python的for语句语法为for X in Y,X是用来遍历Y的变量
每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容
例如,显示给定athlete_list变量来显示athlete列表:

  1. <ul>
  2. {% for athlete in athlete_list %}
  3.     <li>{{ athlete.name }}</li>
  4. {% endfor %}
  5. </ul>

在标签里添加reversed来反序循环列表:

  1. {% for athlete in athlete_list reversed %}
  2. ...
  3. {% endfor %}
  4. {% for %}标签可以嵌套:
  5. {% for country in countries %}
  6.     <h1>{{ country.name }}</h1>
  7.     <ul>
  8.     {% for city in country.city_list %}
  9.         <li>{{ city }}</li>
  10.     {% endfor %}
  11.     </ul>
  12. {% endfor %}

系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值
类似的,系统也不支持continue语句,本章后面的“哲学和限制”会解释设计的原则
{% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息
1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:

  1. {% for item in todo_list %}
  2.     <p>{{ forloop.counter }}: {{ item }}</p>
  3. {% endfor %}

2,forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
4,forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:

  1. {% for object in objects %}
  2.     {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
  3.     {{ object }}
  4.     </li>
  5. {% endfor %}

6,forloop.last当最后一次循环时值为True

  1. {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}

7,forloop.parentloop在嵌套循环中表示父循环的forloop:

  1. {% for country in countries %}
  2.     <table>
  3.     {% for city in country.city_list %}
  4.         <tr>
  5.             <td>Country #{{ forloop.parentloop.counter }} </td>
  6.             <td>City #{{ forloop.counter }}</td>
  7.             <td>{{ city }}</td>
  8.         </tr>
  9.     {% endfor %}
  10.     </table>
  11. {% endfor %}

富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
Django会在for标签的块中覆盖你定义的forloop变量的值
在其他非循环的地方,你的forloop变量仍然可用
我们建议模板变量不要使用forloop,如果你需要这样做来访问你自定义的forloop,你可以使用forloop.parentloop

ifequal/ifnotequal
Django模板系统并不是一个严格意义上的编程语言,所以它并不允许我们执行Python语句
(我们会在‘哲学和限制‘一节详细讨论)。
然而在模板语言里比较两个值并且在他们一致的时候显示一些内容,确实是一个在常见不过的需求了——所以Django提供了ifequal标签。
{% ifequal %}比较两个值,如果相等,则显示{% ifequal %}和{% endifequal %}之间的所有内容:

  1. {% ifequal user currentuser %}
  2.     <h1>Welcome!</h1>
  3. {% endifequal %}

参数可以是硬编码的string,单引号和双引号均可,下面的代码是合法的:

  1. {% ifequal section 'sitenews' %}
  2.     <h1>Site News</h1>
  3. {% endifequal %}
  4. {% ifequal section "community" %}
  5.     <h1>Community</h1>
  6. {% endifequal %}

和{% if %}一样,{% ifequal %}标签支持{% else %}

  1. {% ifequal section 'sitenews' %}
  2.     <h1>Site News</h1>
  3. {% else %}
  4.     <h1>No News Here</h1>
  5. {% endifequal %}

其它的模板变量,strings,integers和小数都可以作为{% ifequal %}的参数:

  1. {% ifequal variable 1 %}
  2. {% ifequal variable 1.23 %}
  3. {% ifequal variable 'foo' %}
  4. {% ifequal variable "foo" %}

其它的Python类型,如字典、列表或booleans不能硬编码在{% ifequal %}里面,下面是不合法的:

  1. {% ifequal variable True %}
  2. {% ifequal variable [123,]%}
  3. {% ifequal variable {'key''value'} %

如果你需要测试某个变量是true或false,用{% if %}即可

注释
和HTML或编程语言如Python一样,Django模板语言允许注释{# #},如:

  1. {# This is a comment #}

模板渲染时注释不会输出,一个注释不能分成多行
下面的模板渲染时会和模板中的内容一样,注释标签不会解析成注释
This is a {# comment goes here
and spans another line #}
test.

过滤器
本章前面提到,模板过滤器是变量显示前转换它们的值的方式,看起来像下面这样:

  1. {{ name|lower }}

这将显示通过lower过滤器过滤后{{ name }}变量的值,它将文本转换成小写
使用(|)管道来申请一个过滤器
过滤器可以串成链,即一个过滤器的结果可以传向下一个
下面是escape文本内容然后把换行转换成p标签的习惯用法:

  1. {{ my_text|escape|linebreaks }}

有些过滤器需要参数,需要参数的过滤器的样子:

  1. {{ bio|truncatewords:"30" }}

这将显示bio标量的前30个字,过滤器参数一直使用双引号
下面是一些最重要的过滤器:
1,addslashed,在任何后斜线,单引号,双引号前添加一个后斜线
当你把一些文本输出到一个JavaScript字符串时这会十分有用
2,date,根据一个格式化string参数来格式化date或datetime对象,例如:

  1. {{ pub_date|date:"F j, Y" }}

格式化string会在附录6定义
3,escape,避免给定的string里出现and符,引号,尖括号
当你处理用户提交的数据和确认合法的XML和XHTML数据时这将很有用
escape将作如下的一些转换:

  1. Converts & to &amp;amp;
  2. Converts < to &amp;lt;
  3. Converts > to &amp;gt;
  4. Converts "(双引号) to &amp;quot;
  5. Converts '(单引号) to &amp;#39;

4,length,返回值的长度,你可以在一个list或string上做此操作
或者在任何知道怎样决定自己的长度的Python对象上做此操作(即有一个__len__()方法的对象)

哲学和限制
现在我们对于Django地模板系统有了一个感性的认识,下面我们将指出一些有意为之的限制和它工作的哲学
不像其他Web程序组件,程序员对模板系统的意见非常不一致
一个很有意思的事实:Python至少拥有数十个——如果没有上百个——的开源模板语言实现,而且看来每一个都是因为其创造者认为现有的模板不能满足他们的要求。
(事实上,据说写一个自己的模板系统是已经成了Python开发者必经的仪式了。如果你还没有写过自己的模板系统,试试看吧,真是很有意思。)
所以,Django的第一个哲学就是Django不强求你使用它的模板语言
Django的目标是提供一个full-stack框架,提供所有必须的web开发模块进行高效开发
很多时候,使用Django的模板系统很方便,但不强求你使用它
下面的“在视图中使用模板”一节我们会看到在Django中使用另一套模板语言,它同样简单易用
但我们仍强烈需要Django的模板语言的工作方式,模板系统深植于World Online和Django发明者的
Web开发方式中,下面是其中一些哲学:
1,业务逻辑应该和呈现逻辑分离
模板系统应该只负责控制显示和显示相关的逻辑我们视模板为一种控制显示和显示相关逻辑的工具,仅此而已。模板系统的功能就止于此。
基于这个原因,Django模板无法直接调用Python代码。在Django模板里,所有的程序设计活动都止于对标签的使用。
虽然你可以自定义模板标签来做任意的事情,但Django自己的模板标签不允许执行Python代码。
2,语法应该和HTML/XML解耦
Django的模板系统采用非HTML格式,如普通的文本,有些其它的模板语言是基于XML的
XML的格式容易输错,并且XML的模板解析速度也容易变得很慢而难以接受
3,页面设计者被假定为熟悉HTML代码
Django模板系统没有设计成可以在Dreamweaver等WYSISYG编辑器中显示良好
这类编辑器有很多限制,Django希望模板作者直接编辑HTML时感到舒适
4,页面设计者被假定为不是Python程序员
模板系统的作者意识到大部分Web页面的模板是页面设计者写的而不是Python程序员写的
他们不具备Python知识,但Django也允许模板用Python来写,它提供了一种直接编写Python代码
来扩展模板系统的方法(第10章会介绍更多)
5,目标不是发明一种编程语言
目标只是提供足够的编程功能,如分支和循环等决定呈现相关的逻辑用
由于上述的设计哲学,Django模板系统产生如下限制:
1,模板不能设置和改变变量的值
可以通过自定义模板标签来达到这个目标(I参看第10章),但是内置Django模板标签不允许这样做
2,模板不能调用原生Python代码
但是也可以通过自定义标签来做这件事情

在视图里使用模板
我们已经学习了使用模板系统的基础,现在我们来在前一章中的current_datetime视图中使用它:

  1. from django.http import HttpResponse
  2. import datetime
  3. def current_datetime(request):
  4.     now = datetime.datetime.now()
  5.     html = "<html><body>It is now %s.</body></html>" % now
  6.     return HttpResponse(html)

让我们把这个试图改成Django模板系统的做法,首先你可能想这样做:

  1. from django.template import Template, Context
  2. from django.http import HttpResponse
  3. import datetime
  4. def current_datetime(request):
  5.     now = datetime.datetime.now()
  6.     t = Template("<html><body>It is now {{ current_date }}.</body></html>")
  7.     html = t.render(Context({'current_date': now}))
  8.     return HttpResponse(html)

这当然用到了模板系统,但它并没有解决我们本章开始介绍的问题,模板仍然嵌在Python代码里面
让我们通过把模板放在一个单独的文件里来解决它,一个简陋的方式就是把模板保存在文件系统中然后使用Python内建的文件读取功能得到模板的内容,下面来看看这样做的例子:

  1. from django.template import Template, Context
  2. from django.http import HttpResponse
  3. import datetime
  4. def current_datetime(request):
  5.     now = datetime.datetime.now()
  6.     # Simple, "dumb" way of saving templates on the filesystem.
  7.     # This doesn't account for missing files!
  8.     fp = open('/home/djangouser/templates/mytemplate.html')
  9.     t = Template(fp.read())
  10.     fp.close()
  11.     html = t.render(Context({'current_date': now}))
  12.     return HttpResponse(html)

这种方式非常不优雅“
1,它不会处理丢失的文件,如果mytemplate.html不存在或者不可读,调用open()将触发IOError异常
2,它硬编码了你的模板位置,如果你使用这个技术来处理每个视图方法,你就会重复复制模板的位置
3,它引入了许多无聊代码,调用open(),fp.reand()和fp.close()需要很多输入而且毫无创造性
为了解决这个问题,我们将使用模板载入和模板目录

模板载入
Django提供了方便和强大的API来从硬盘载入模板,从而减少调用模板和模板本身的冗余
为了使用Django的模板载入API,首先你需要在settings文件里告诉Django你把模板放在哪
Django的settings文件时存放你的Django实例的配置的地方,它是一个简单的具有
模块级变量的Python模块,其中每个设置都是一个变量
当你运行django-admin.py startproject mysite时脚本会为你创建一个默认的settings文件settings.py
看看这个文件的内容,它包含了像下面这样的变量:

  1. DEBUG = True
  2. TIME_ZONE = 'America/Chicago'
  3. USE_I18N = True
  4. ROOT_URLCONF = 'mysite.urls'

它把自己解释的很清楚,这些设置和对应的值是简单的Python变量
由于settings文件仅仅是一个普通的Python模块,你可以在设置新变量前做类似于检查某个变量的值等动态的事情,这将避免你的settings文件出现Python语法错误
这也意味着你应该避免在settings文件里面出现Python的语法错误
后面我们会深入讲解settings文件,现在先来看看TEMPLATE_DIRS设置,它告诉Django的模板载入机制在哪里寻找模板
默认情况下它是一个空的元组,选择一个你喜欢的存放模板的地方并添加到TEMPLATE_DIRS中去:

  1. TEMPLATE_DIRS = (
  2.     '/home/django/mysite/templates',
  3. )

需要注意的一些事情:
1,你可以指定任何目录,只要那个目录下的目录和模板对于你的Web服务器运行时的用户是可读的
如果你找不到一个放置模板的位置,我们推荐你在Django工程目录下创建一个templates目录
2,不要忘了模板目录最后的逗号,Python需要逗号来区分单元素元组和括号括起来的语句
这是新手经常犯的错误,如果你想避免这个错误,可以用列表来替代元组,单元素列表不需要结尾的逗号

  1. TEMPLATE_DIRS = [
  2.     '/home/django/mysite/templates'
  3. ]

元组比列表略微高效,所以我们推荐使用元组
3,使用绝对路径很简单,如果你想更灵活和松耦合,你可利用Django的settings文件是简单的Python代码
这点来动态构建TEMPLATE_DIRS内容,例如:

  1. import os.path
  2. TEMPLATE_DIRS = (
  3.     os.path.join(os.path.dirname(__file__), 'templates'),
  4. )

这个例子使用了富有魔力的Python变量__file__,它会被自动设成当前代码所在的Python模块的文件名
4,如果你使用Windows,加上硬盘号并使用Unix风格的前斜线而不是后斜线,例如:

  1. TEMPLATE_DIRS = (
  2.     'C:/www/django/templates',
  3. )

设置好TEMPLATE_DIRS,下一步就是使用Django的模板载入功能而不是硬编码模板路径来测试代码
让我们回到current_datetime视图看看:

  1. from django.template.loader import get_template
  2. from django.template import Context
  3. from django.http import HttpResponse
  4. import datetime
  5. def current_datetime(request):
  6.     now = datetime.datetime.now()
  7.     t = get_template('current_datetime.html')
  8.     html = t.render(Context({'current_date': now}))
  9.     return HttpResponse(html)

这个例子中我们使用了django.template.loarder.get_template()方法而不是从文件系统手动载入模板
get_template()方法使用模板名作为参数,算出模板在文件系统的什么地方,打开它并返回编译好的Template对象
如果get_template()方法不能找到给定名字的模板,它将触发TemplateDoesNotExist异常
为了看看到底是什么样子,启动Djang server,打开浏览器访问http://127.0.0.1:8000/now/
假设你的DEBUG设为True并且你没有创建current_datetime.html模板,你将看到一个高亮显示
TemplateDoesNotExist异常的出错页面
出错页面和第3章那个很类似,但它还有一个“Template-loader postmortem”部分
这个部分告诉你Django尝试载入哪个模板以及每个尝试失败了的原因(如“File does not exist”)
当你尝试debug模板载入错误时这些信息是非常有价值的
如同你能在出错信息中看到的一样,Django试图把TEMPLATE_DIRS中设置的值和传入get_template()方法的模板名字组合起来查找模板文件。
如果你的TEMPLATE_DIRS中包含'/home/django/templates',最后查找到的文件可能像这样:'/home/django/templates/current_datetime.html.'
接下来,在你的模板目录下创建current_datetime.html文件并使用如下的模板代码:

  1. <html><body>It is now {{ current_date }}.</body></html>

刷新浏览器页面你将看到完整渲染的页面

render_to_response()
Django提供了一个捷径来使用一行代码完成载入模板,填充Context,渲染模板,返回HttpResponse对象的工作
这就是render_to_response(),它在django.shortcuts模块下
大部分情况下,你都会使用render_to_response()而不是手动完成上述的事情
下面是利用render_to_response()把current_datetime重写后的例子:

  1. from django.shortcuts import render_to_response
  2. import datetime
  3. def current_datetime(request):
  4.     now = datetime.datetime.now()
  5.     return render_to_response('current_datetime.html', {'current_date': now})

多么不同啊!我们来看看这些代码:
1,我们不在import get_template,Template,Context或者HttpResponse
相反,我们import django.shortcuts.render_to_response,import datetime仍然存在
2,使用current_datetime方法,我们仍然计算now,但载入模板,创建context,渲染模板和
创建HttpResponse全部被render_to_response()替换,render_to_response返回HttpResponse对象
render_to_response()的第一个参数应该是使用的模板名,对应到模板目录的相对路径
第二个参数如果有的话应该是一个用来创建Context的字典
如果你不提供第二个参数,render_to_response()将使用一个空的字典

locals()小技巧
看看最近的current_datetime:

  1. def current_datetime(request):
  2.     now = datetime.datetime.now()
  3.     return render_to_response('current_datetime.html', {'current_date': now})

这个例子中你会发现你自己计算一些值后存储在变量中(例如now)并传递给模板
懒程序员可能会觉得有点繁琐,既要给临时变量取名又要给模板变量取名
这不仅仅是冗余,这是过度输入
如果你很懒或者你想保持代码整洁,使用Python内建的locals()方法
locals()返回一个包含当前作用域里面的所有变量和它们的值的字典,上面的代码可以重写:

  1. def current_datetime(request):
  2.     current_date = datetime.datetime.now()
  3.     return render_to_response('current_datetime.html', locals())

这里我们传递locals()的值而不是手动指定context字典,locals()包含了所有定义在当前方法的变量
而且,我们把now变量重命名为current_date,因为模板需要的是这个变量名
这个例子中locals()不会给你太大改善,但这个技术可以帮你少敲键盘
使用locals()需要注意的是它包含了所有当前变量,可能包括比你的模板想访问的更多的变量
上面的例子中,locals()也包括request变量,这依赖于你的程序
最后要注意的是locals()导致了一点点开销,因为Python不得不动态创建字典
如果你手动指定context字典则可以避免这项开销

get_template()的子目录
将所有的模板都放在同一个目录下是很笨的方式,你可能想把模板存放模板目录的子目录下
这是可以的,事实上我们推荐这样做,并且一些其它高级Django特性,如第9章会提到的generic view系统
也希望这样的模板结构作为默认的惯例用法
达到这点很容易,如果你希望访问子目录下的模板,只需在模板名前面添加子目录名和斜线即可:

  1. t = get_template('dateapp/current_datetime.html')

因为render_to_response()是对get_template()的小包装,你可以在它身上作同样的事情
对子目录的深度并没有限制,Windows用户注意使用前斜线而不是后斜线,get_template()使用Unix风格文件名

include模板标签
我们已经学习了模板载入机制,我们要介绍一个利用这个机制的内建标签:{% include %}
这个标签允许你引入另一个模板的内容,标签的参数是你想引入的模板的名字,名字可以是变量,
也可以是单引号或双引号表示的string
下面两个例子引入了模板nav.html的内容,这表示单引号和双引号都是允许的:

  1. {% include 'nav.html' %}
  2. {% include "nav.html" %}

下面的例子引入了includes/nav.html模板:

  1. {% include 'includes/nav.html' %}

下面的例子引入了一个名字存在于template_name变量中的模板:

  1. {% include template_name %}

和get_template()一样,请求的模板名前面会加上TEMPLATE_DIRS
如果被引入的模板中包含任何的模板代码,如标签和变量等,它将用父模板的context计算它们
如果给定的模板名不存在,Django将做下面两件事情中的一件:
1,如果DEBUG设置为True,你将看到一个TemplateDoesNotExist异常的错误页面
2,如果DEBUG设置为False,标签将什么也不显示

模板继承
我们的模板例子现在还是HTML片断,但是真实世界你将使用Django模板系统输出完整的HTML页面
这将导致常见的Web开发问题:怎样减少一个常见页面区域的重复和冗余(如全站导航)?
解决这个问题的经典方式是使用服务器端引入和导向,你可以在你的HTML里面嵌套另一个页面
Django确实也支持这种方式,上面介绍的{% include %}模板标签就是这种方案
但是解决这个问题的更好的方式是Django的更优雅的方式模板继承
本质上来说,模板继承使你能够构建一个“骨架”模板,里面包含你的网站的通用部分,并且在里面
定义子模板可以覆盖的“块”,让我们看看前面的例子,编辑current_datetime.html文件:

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  2. <html lang="en">
  3. <head>
  4.     <title>The current time</title>
  5. </head>
  6. <body>
  7.     <h1>My helpful timestamp site</h1>
  8.     <p>It is now {{ current_date }}.</p>
  9.     <hr>
  10.     <p>Thanks for visiting my site.</p>
  11. </body>
  12. </html>

看起来不错,但是当我们为另一个视图创建另一个模板时(如hours_ahead视图),如果我们想再创建
一个完整的合法的HTML模板,我们将创建下面的内容:

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  2. <html lang="en">
  3. <head>
  4.     <title>Future time</title>
  5. </head>
  6. <body>
  7.     <h1>My helpful timestamp site</h1>
  8.     <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
  9.     <hr>
  10.     <p>Thanks for visiting my site.</p>
  11. </body>
  12. </html>

显然我们重复了很多HTML内容,想象一下,如果我们在每个页面都有一些样式表,导航条,JavaScript...
我们将会在每个模板加入重复的HTML内容
这个问题的服务器端解决方案是取出模板中通用的部分然后存放在一个单独的模板中,然后被每个模板引入
可能你会把它们存放在一个叫header.html中:

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  2. <html lang="en">
  3. <head>

可能还需把底下的东西存在一个叫footer.html的文件中:
<hr>
<p>Thanks for visiting my site.</p>
</body>
</html>
使用基于引入的策略,头和尾很容易,但是中间的东西就很混乱
例子中,每个页面有一个title

  1. <h1>My helpful timestamp site</h1>

但是title不能放到hear.html中,因为每个页面中的title是不同的
Django的模板继承系统解决了这种问题,你可以认为它是

简单记录squid搭建一个透明代理缓存服务器

外网:

eth0 Link encap:Ethernet HWaddr 00:0C:29:02:DC:6B
inet addr:192.168.96.132 Bcast:192.168.96.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe02:dc6b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:118 errors:0 dropped:0 overruns:0 frame:0
TX packets:89 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:12283 (11.9 KiB) TX bytes:14421 (14.0 KiB)

内网:

eth1 Link encap:Ethernet HWaddr 00:0C:29:02:DC:75
inet addr:10.8.8.205 Bcast:10.8.8.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe02:dc75/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1496 errors:0 dropped:0 overruns:0 frame:0
TX packets:25 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:97417 (95.1 KiB) TX bytes:1608 (1.5 KiB)

 

主要实现原理:

当代理服务器中客户端需要的数据时:

a. 客户端向代理服务器发送数据请求;

b. 代理服务器检查自己的数据缓存;

c. 代理服务器在缓存中找到了用户想要的数据,取出数据;

d. 代理服务器将从缓存中取得的数据返回给客户端。

当代理服务器中没有客户端需要的数据时:

1. 客户端向代理服务器发送数据请求;

2. 代理服务器检查自己的数据缓存;

3. 代理服务器在缓存中没有找到用户想要的数据;

4. 代理服务器向Internet 上的远端服务器发送数据请求;

5. 远端服务器响应,返回相应的数据;

6. 代理服务器取得远端服务器的数据,返回给客户端,并保留一份到自己的数据缓存中。

 

安装squid:debian/ubuntu:apt-get update & apt-get install squid -y         centos:yum update & yum install squid -y

 

检查squid是否开机启动:chkconfig,若不是开机启动则设置为开机启动:chkconfig --level 35 squid on

 

squid 的主配置文件是 /etc/squid/squid.conf,红色为重点配置

 

http_port 3128      //设置监听的IP与端口号

cache_mem 64 MB      //额外提供给squid使用的内存,squid的内存总占用为 X * 10+15+“cache_mem”,其中X为squid的cache占用的容量(以GB为单位),
//比如下面的cache大小是100M,即0.1GB,则内存总占用为0.1*10+15+64=80M,推荐大小为物理内存的1/3-1/2或更多。
maximum_object_size 4 MB   //设置squid磁盘缓存最大文件,超过4M的文件不保存到硬盘

minimum_object_size 0 KB   //设置squid磁盘缓存最小文件

maximum_object_size_in_memory 4096 KB   //设置squid内存缓存最大文件,超过4M的文件不保存到内存

cache_dir ufs /var/spool/squid 100 16 256   //定义squid的cache存放路径 、cache目录容量(单位M)、一级缓存目录数量、二级缓存目录数量

logformat combined %&gt;a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st "%{Referer}>h" "%{User-Agent}&gt;h" %Ss:%Sh //log文件日志格式

access_log /var/log/squid/access.log combined  //log文件存放路径和日志格式

cache_log /var/log/squid/cache.log   //设置缓存日志

logfile_rotate 60   //log轮循 60天

cache_swap_high 95  //cache目录使用量大于95%时,开始清理旧的cache

cache_swap_low 90   //cache目录清理到90%时停止。

acl localnet src 10.8.8.0/24  //定义本地网段

http_access allow localnet  //允许本地网段使用

http_access deny all  //拒绝所有

visible_hostname squid.david.dev  //主机名

cache_mgr mchina_tang@qq.com  //管理员邮箱

 

配置好squid后初始化:squid -z

 

启动squid:service squid start

 

打开浏览器-设置-更改代理服务器设置-局域网设置-代理服务器

地址:10.8.8.205   端口:3128     

勾上-确定

 

 

随便打开一个网页,能正常打开并刷新说明此事squid的正向代理是通的

 

接下来配置防火墙,利用防火墙透明代理:

debian7/ubuntu14.04:vi /etc/iptables.rules

centos6:vi /etc/sysconfig/iptables

注意:centos7与debian8默认不是iptables,而是firewalld,请关闭firewalld开机启动,并安装iptables设置开机启动

iptables -t nat -I PREROUTING -i eth0 -s 10.8.8.0/24 -p tcp --dport 80 -j REDIRECT --to-port 3128

保存:service iptables save

重启:service iptables restart

 

修改本地网关为:10.8.8.205

 

 

 

保存,重新打开网页,能正常打开网页说明透明代理已成功

 

若不能则尝试清空防火墙,清空时请先备份:

debian7/ubuntu14.04:cp /etc/iptables.rules /etc/iptables.rules.bak

centos6:cp /etc/sysconfig/iptables /etc/sysconfig/iptables.bak

iptables -F

保存:service iptables save

重启:service iptables restart

若此时透明代理正常,则判断是否受到FORWARD规则的影响,

删除空的防火墙规则,恢复备份:

debian7/ubuntu14.04:rm  /etc/iptables.rules & mv /etc/iptables.rules.bak /etc/iptables.rules

centos6:rm  /etc/sysconfig/iptables & mv /etc/sysconfig/iptables.bak /etc/sysconfig/iptables

 

编辑防火墙规则,并注释关于FORWARD的规则,

保存:service iptables save

重启:service iptables restart

若此时透明代理正常则说明FORWARD规则存在问题,请检查规则规则

若依然无法进行透明代理,则检查squid配置文件,或检查是否已开启路由模式:vi /etc/sysctl.conf    检查net.ipv4.ip_forward = 1

保存重启

Nginx+UWSGI+Django配置全过程

Nginx + uwsgi + Django 安装配置

一、安装Nginx uwsgi Django

安装tengine


yum install pcre-devel -y 
wget http://tengine.taobao.org/download/tengine-2.1.1.tar.gz
tar xf tengine-2.1.1.tar.gz
cd tengine-2.1.1
./configure
make
make installl


wget https://www.djangoproject.com/m/releases/1.4/Django-1.4.22.tar.gz
tar xf Django-1.4.22.tar.gz
cd Django-1.4.22
python setup.py install


安装uwsgi#安装位置默认在/usr/local/nginx

安装Django


pip install uwsgi



#!/usr/bin/env python
#coding:utf8
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return ["Hello World"]

执行命令:二、配置

1、测试uwsgi代理功能

测试文件test.py

uwsgi --http :8000 --wsgi-file test.py



在浏览器中访问,http://localhost:8000 如果出现Hello World 则说明uwsgi代理正常工作

2、测试uwsgi 启动django项目

创建项目:

# django-admin startproject myapp

在myapp/myapp/有一个wsgi.py文件

执行命令:

# cd myapp

# uwsgi --http :8000 --wsgi-file myapp/wsgi

在浏览器中访问http://localhost:8000

如果网页正常则一切顺利。。。。。。

说明:从客户商到 uWSGI 再到 Django 是正常的,uwsgi可以正常启动django项目

3、配置nginx + uwsgi + django

首先配置使用http的方式:

编辑配置文件/usr/local/nginx/conf/nginx.conf

内容如下:

user  nginx; #使用nginx用户
    worker_processes  2;
    events {
        use epoll;
        worker_connections  65535;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        tcp_nopush     on;
        keepalive_timeout  65;
        gzip  on;
        upstream django {
            server 127.0.0.1:8001;
        }
        server {
            listen       80;
            server_name  localhost;
            client_max_body_size 75M;
                location / {
                uwsgi_pass django;
                include uwsgi_params;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
     }
uwsgi --http :8001 --wsgi-file myapp/wsgi

使用浏览器访问http://localhost 应该用正常访问,出现以下图片:wKiom1XdTRTjyyPXAAGbKGgXMf4577.jpg用UNIX socket取代tcp port执行命令:

修改nginx.conf
    upstream django {
            #server 127.0.0.1:8001;
            server unix:///test/myapp.sock;
        }
uwsgi --socket /test/myapp.sock --wsgi-file myapp.wsgi

到此nginx+uwsgi+django已经初步实现了,下面来为uwsgi设置一个配置文件

4、配置myapp_uwsgi.ini

在Django项目目录下创建myapp_uwsgi.ini 内容如下:来创建/test这个目录

mkdir /test

chown nginx:nginx /test #如果不修改用户权限,nginx无法访问此socket 无法实现代理

会报如下错误:

connect() to unix:///test/myapp.sock failed (13: Permission denied)

启动:

[uwsgi]
uid = nginx  #使用nginx用户和组
gid = nginx
chdir = /usr/local/myapp #指定项目目录
module = myapp.wsgi #加载myapp/wsgi.py这个模块
master = true  #启动主进程。
processes = 2 #启动2个工作进程
listen = 120 #设置socket的监听队列大小(默认:100)
socket = /test/myapp.sock #指定socket文件
pidfile = /var/run/uwsgi.pid #指定pid文件
vacuum = true #当服务器退出的时候自动删除unix socket文件和pid文件。
enable-threads = true #允许用内嵌的语言启动线程。这将允许你在app程序中产生一个子线程
buffer-size = 32768 #设置用于uwsgi包解析的内部缓存区大小为64k。默认是4k。
reload-mercy = 8 #设置在平滑的重启(直到接收到的请求处理完才重启)一个工作子进程中,等待这个工作结束的最长秒数。这个配置会使在平滑地重启工作子进程中,如果工作进程结束时间超过了8秒就会被强行结束(忽略之前已经接收到的请求而直接结束)
max-requests = 5000 #为每个工作进程设置请求数的上限。当一个工作进程处理的请求数达到这个值,那么该工作进程就会被回收重用(重启)。你可以使用这个选项来默默地对抗内存泄漏
limit-as = 256 #通过使用POSIX/UNIX的setrlimit()函数来限制每个uWSGI进程的虚拟内存使用数。这个配置会限制uWSGI的进程占用虚拟内存不超过256M。如果虚拟内存已经达到256M,并继续申请虚拟内存则会使程序报内存错误,本次的http请求将返回500错误。
harakiri = 60 #一个请求花费的时间超过了这个harakiri超时时间,那么这个请求都会被丢弃,并且当前处理这个请求的工作进程会被回收再利用(即重启)
daemonize = /var/log/myapp_uwsgi.log # 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器
uwsgi --ini myapp_uwsgi.ini

测试是否正常,如果不正常,可以查看日志,排错。

到此Nginx  +  Uwsgi + Django配置完成 ,并正常使用。整个过程走了很坑,找了很文章和资料,uwsgi还有很多选项,参考了网友的文章

参考链接:

http://www.jianshu.com/p/e6ff4a28ab5a

http://heipark.iteye.com/blog/1847421

 

原文:http://zhou123.blog.51cto.com/4355617/1688434启动: