Django学习笔记2


10 在url文件里直接导入view函数的时候,貌似要加引号,不知道为什么,先记录下来。要不然就先在前面用import导入进来,然后url函数里直接使用。

另入,像第二个,我平时是这么写的:

url(r'^hello/$', 'app.viwes.hello`),
CSRF token missing or incorrect

--

 

1 在 templete 中, 为每个 POST form 增加一个 {% csrf_token %} tag. 如下:

 

<form>

    {% csrf_token %}

</form>

 

2 在 view 中, 使用 django.template.RequestContext 而不是 Context.

 

render_to_response, 默认使用 Context. 需要改成 RequestContext.

 

导入 class:

 

from django.template import RequestContext

 

给 render_to_response 增加一个参数:

 

def your_view(request):

    ...

    return render_to_response('template.html',

          your_data,

          context_instance=RequestContext(request)

    )

还有一个办法,直接在setting.py里注释掉  

'django.middleware.csrf.CsrfViewMiddleware'

12 class Meta

尽管很灵活,但是每次都要用 order_by() 显得有点啰嗦。 大多数时间你通常只会对某些 字段进行排序。 在这种情况下,Django让你可以指定模型的缺省排序方式:

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 Meta:**
        **ordering = ['name']**

现在,让我们来接触一个新的概念。 class Meta,内嵌于 Publisher 这个类的定义中(如果 class Publisher 是顶格的,那么 class Meta 在它之下要缩进4个空格--按 Python 的传统 )。你可以在任意一个 模型 类中使用Meta 类,来设置一些与特定模型相关的选项。 在 附录B 中有 Meta 中所有可选项的完整参考,现在,我们关注ordering 这个选项就够了。 如果你设置了这个选项,那么除非你检索时特意额外地使用了 order_by(),否则,当你使用 Django 的数据库 API 去检索时,Publisher对象的相关返回值默认地都会按 name 字段排序。

13 QuerySet

Throughout the book you’ve seen objects retrieved using code like the following:

>>> blogs = Blog.objects.filter(author__name__contains="Joe")

There are quite a few “moving parts” behind the scenes here: when you retrieve objects from the database, you’re actually constructing aQuerySet using the model’s Manager. This QuerySet knows how to execute SQL and return the requested objects.

Appendix A looked at both of these objects from a model-definition point of view; now we’ll look at how they operate.

A QuerySet represents a collection of objects from your database. It can have zero, one, or manyfilters – criteria that narrow down the collection based on given parameters. In SQL terms, aQuerySet equates to a SELECT statement, and a filter is a WHERE.

You get a QuerySet by using your model’s Manager. Each model has at least one Manager, and it’s calledobjects by default. Access it directly via the model class, like so:

>>> Blog.objects
<django.db.models.manager.Manager object at 0x137d00d>

Managers are accessible only via model classes, rather than from model instances, to enforce a separation between “table-level” operations and “record-level” operations:

>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Manager isn't accessible via Blog instances.

The Manager is the main source of QuerySets for a model. It acts as a “root” QuerySet that describes all objects in the model’s database table. For example,Blog.objects is the initial QuerySet that contains all Blog objects in the database.

Caching and QuerySets

Each QuerySet contains a cache, to minimize database access. It’s important to understand how it works, in order to write the most efficient code.

In a newly created QuerySet, the cache is empty. The first time aQuerySet is evaluated – and, hence, a database query happens – Django saves the query results in theQuerySet‘s cache and returns the results that have been explicitly requested (e.g., the next element, if theQuerySet is being iterated over). Subsequent evaluations of theQuerySet reuse the cached results.

Keep this caching behavior in mind, because it may bite you if you don’t use yourQuerySets correctly. For example, the following will create twoQuerySets, evaluate them, and throw them away:

print [e.headline for e in Entry.objects.all()]
print [e.pub_date for e in Entry.objects.all()]

That means the same database query will be executed twice, effectively doubling your database load. Also, there’s a possibility the two lists may not include the same database records, because anEntry may have been added or deleted in the split second between the two requests.

To avoid this problem, simply save the QuerySet and reuse it:

queryset = Poll.objects.all()
print [p.headline for p in queryset] # Evaluate the query set.
print [p.pub_date for p in queryset] # Reuse the cache from the evaluation.

14 ForeignKey/ ManyToManyField

访问外键(Foreign Key)值

当你获取一个ForeignKey 字段时,你会得到相关的数据模型对象。 例如:

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

对于用`` ForeignKey`` 来定义的关系来说,在关系的另一端也能反向的追溯回来,只不过由于不对称性的关系而稍有不同。 通过一个`` publisher`` 对象,直接获取 books ,用 publisher.book_set.all() ,如下:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

实际上,book_set 只是一个 QuerySet(参考第5章的介绍),所以它可以像QuerySet一样,能实现数据过滤和分切,例如:

1

>>> 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组成的。

访问多对多值(Many-to-Many Values)

多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。 例如,这里是如何查看书籍的作者:

>>> 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')
[]

反向查询也可以。 要查看一个作者的所有书籍,使用author.book_set ,就如这样:

>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]

这里,就像使用 ForeignKey字段一样,属性名book_set是在数据模型(model)名后追加_set

15 session

打开 Sessions功能

Sessions 功能是通过一个中间件(参见第17章)和一个模型(model)来实现的。 要打开sessions功能,需要以下几步操作:

4

  1. 编辑 MIDDLEWARE_CLASSES 配置,确保 MIDDLEWARE_CLASSES 中包含'django.contrib.sessions.middleware.SessionMiddleware'

  1. 确认 INSTALLED_APPS 中有 'django.contrib.sessions' (如果你是刚打开这个应用,别忘了运行manage.py syncdb )

在视图中使用Session

SessionMiddleware 激活后,每个传给视图(view)函数的第一个参数``HttpRequest`` 对象都有一个 session 属性,这是一个字典型的对象。 你可以象用普通字典一样来用它。 例如,在视图(view)中你可以这样用:

2

# Set a session value:
request.session["fav_color"] = "blue"

# Get a session value -- this could be called in a different view,
# or many requests later (or both):
fav_color = request.session["fav_color"]

# Clear an item from the session:
del request.session["fav_color"]

# Check if the session has a given key:
if "fav_color" in request.session:

在视图(View)外使用Session

从内部来看,每个session都只是一个普通的Django model(在 django.contrib.sessions.models 中定义)。每个session都由一个随机的32字节哈希串来标识,并存储于cookie中。 因为它是一个标准的模型,所以你可以使用Django数据库API来存取session。

1

>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

浏览器关闭即失效会话 vs 持久会话

你可能注意到了,Google给我们发送的cookie中有 expires=Sun, 17-Jan-2038 19:14:07 GMT; cookie可以有过期时间,这样浏览器就知道什么时候可以删除cookie了。 如果cookie没有设置过期时间,当用户关闭浏览器的时候,cookie就自动过期了。 你可以改变 SESSION_EXPIRE_AT_BROWSER_CLOSE 的设置来控制session框架的这一行为。

缺省情况下, SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,这样,会话cookie可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(缺省设置是两周,即1,209,600 秒)。 如果你不想用户每次打开浏览器都必须重新登陆的话,用这个参数来帮你。

如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True ,当浏览器关闭时,Django会使cookie失效。

16 Middleware

Django项目的安装并不强制要求任何中间件,如果你愿意, MIDDLEWARE_CLASSES 可以为空。

这里中间件出现的顺序非常重要。 在request和view的处理阶段,Django按照 MIDDLEWARE_CLASSES 中出现的顺序来应用中间件,而在response和异常处理阶段,Django则按逆序来调用它们。 也就是说,Django将MIDDLEWARE_CLASSES 视为view函数外层的顺序包装子: 在request阶段按顺序从上到下穿过,而在response则反过来。

17和遗留Web应用集成

同由其他技术驱动的应用一样,在相同的Web服务器上运行Django应用也是可行的。 最简单直接的办法就是利用Apaches配置文件httpd.conf,将不同的URL类型分发至不同的技术。 (请注意,第12章包含了在Apache/mod_python上配置Django的相关内容,因此在尝试本章集成之前花些时间去仔细阅读第12章或许是值得的。)

关键在于只有在您的httpd.conf文件中进行了相关定义,Django对某个特定的URL类型的驱动才会被激活。 在第12章中解释的缺省部署方案假定您需要Django去驱动某个特定域上的每一个页面。

<Location "/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonDebug On
</Location>

这里, <Location "/"> 这一行表示用Django处理每个以根开头的URL.

精妙之处在于Django将<location>指令值限定于一个特定的目录树上。 举个例子,比如说您有一个在某个域中驱动大多数页面的遗留PHP应用,并且您希望不中断PHP代码的运行而在../admin/位置安装一个Django域。 要做到这一点,您只需将<location>值设置为/admin/即可。

<Location "/admin/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonDebug On
</Location>

有了这样的设置,只有那些以/admin/开头的URL地址才会触发Django去进行处理。 其他页面会使用已存在的设置。

请注意,把Diango绑定到的合格的URL(比如在本章例子中的 /admin/ )并不会影响其对URL的解析。 绝对路径对Django才是有效的(例如 /admin/people/person/add/ ),而非截断后的URL(例如 /people/person/add/)。这意味着你的根URLconf必须包含前缀 /admin/ 。






你可能感兴趣的:(Django学习笔记2)