文章目录
  1. 1. 一、settings
  2. 2. 二、url conf
  3. 3. 三、view
  4. 4. 四、模板
  5. 5. {*{ story.headline|upper }}
  6. 6. 五、form表单
  • 有定义模块
    1. 1. 六、model
  • 原文地址:django 学习总结(1.5版) 作者:bailiangcn

    本人转载的地址,还是多看看文档,多实践

    http://blog.chinaunix.net/uid-23500957-id-3838222.html

    django的调度逻辑图

    目录

    1. setting
    2. url 转发
    3. view 视图
    4. django 模版
    5. form 表单
    6. model

    一、settings

    • 引用setting项
    from django.conf import settings
      urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 
    

    二、url conf

    主页url文档

    • urlpatterns 是所有url的链表,可以 +=
    from django.conf.urls import patterns, include, url
      urlpatterns = patterns('',)
      urlpatterns += patterns('',
          url(r'^tag/(?P<tag>\w+)/$', 'tag'),) 
    
    • 可以使用 include来引用 app内部urls.py文件
    url(r'^elist/', include('elist.urls')), 
    
    • url中引用参数
    在需要捕捉的地方用括号括起来  
      (r'homeworklist/edit/([^/]+)/$', edit_homeworklist),
      调用结果:edit_homeworklist(request,参数)
    
      命名参数 ?P<name>
      (r'homeworklist/edit/(?P<id>[^/]+)/$', edit_homeworklist),
      调用结果:edit_homeworklist(request,id='参数') 
    
    • patterns的前缀字符串,用于缩短视图函数
    urlpatterns = patterns('',
      url(r'^articles/(\d{4})/$', 'news.views.year_archive'),)
    
          等价:
      urlpatterns = patterns('new.views',
      url(r'^articles/(\d{4})/$', 'year_archive'),) 
    
    • url() 函数
    格式:
      url(regex, view, kwargs=None, name=None, prefix='')
      传递参数:
      url(r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}), 
    

    命名 url

    url(r'^archive/(\d{4})/$', archive, name="full-archive"),
      url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, name="arch-summary"), 
    
    在模板中使用
      // url 'arch-summary' 1945 //
      // url 'full-archive' 2007 // 
    
    • url的反向解析
    - In templates: Using the url template tag.
    - In Python code: Using the django.core.urlresolvers.reverse() function.
    - In higher level code related to handling of URLs of Django model instances: The get_absolute_url() method.
    

    详细文档

    • redirect() 文档

    虽然这个函数不属于 url conf配置的一部分,但是他在功能上起到转向分发的作用,所以我也把他放到这一节。 常见的使用方法:

    1. 传入一个对象,返回访问这个对象的url(推荐使用reverse())
    2. 传入一个url,进行跳转

    return redirect(‘/some/url/‘)
    return redirect(‘http://example.com/‘)

    三、view

    输入 request, 返回 response.

    • HttpResponse (最简单)

    文档

    from django.http import HttpResponse

    html = “It is now %s.” % now
    return HttpResponse(html)

    • render_to_response

    文档

    from django.shortcuts import render_to_response 
    

    render_to_response(template_name[, dictionary][, context_instance][, content_type])

    范例

    return render_to_response(‘myapp/index.html’, {“foo”: “bar”},

    mimetype="application/xhtml+xml") 
    

    默认的 render_to_response 是不包含 request ,如果要使用 HttpRequest, 需要手工定义 context_instance=RequestContext(request)

    return render_to_response('my_template.html',
              my_data_dictionary,
              context_instance=RequestContext(request)) 
    
    • render (应用模板,比较简洁)

    文档 ,默认使用 RequestContext 的 render_to_response

    from django.shortcuts import render 
    

    render(request, template_name[, dictionary][, context_instance]

    [, content_type][, status][, current_app]) 
    
    1. request
    2. 模板名称
    3. 附加字典
    4. 上下文对象
    5. 内容类型
    6. 状态 200 404 500

    return render(request, ‘myapp/index.html’, {“foo”: “bar”},

    content_type="application/xhtml+xml") 
    

    和 django.template 下的 手工loader 等效

    t = loader.get_template(‘myapp/template.html’)
    c = RequestContext(request, {‘foo’: ‘bar’})
    return HttpResponse(t.render(c),
    content_type=”application/xhtml+xml”)

    四、模板


    // extends "base_generic.html" //
    
               // block title //{*{ section.title }}// endblock //
    
               // block content //
               <h1>{*{ section.title }}</h1>
    
               // for story in story_list //
    

    {*{ story.headline|upper }}

    {*{ story.tease|truncatewords:”100” }}

    // endfor // // endblock //


    • 变量

    {*{ 变量名 }}

    - 点的解释顺序 
    
    1.字典
    2.属性
    3.方法
    4.列表索引 
    
    • 过滤器

    可以用来修饰变量,{{变量名|过滤器}}
    使用参数的例子 {
    { value|add:”2” }}
    内置的过滤器目录

    - default 默认值 {*{ value|default:"nothing" }}
    
    • 标签

    // 标签名称 //
    内置的模板标签目录

    - for endfor
    - for ... empty
    - if elif else endif
    - **** 单行注释
    - **// comment // ... // endcomment //** 多行注释
    - **// verbatim // ... // endverbatim //** 禁止 render ,比如包围javascript模板
    - **<form action="." method="post">// csrf_token //** 保护
    - **now** 现在日期、时间 详细格式
    

    It is // now “jS F Y H:i” //

    - **// cycle 'row1' 'row2' //** 交替 详细文档
    - **regroup** 可以根据字段、属性进行分组 详细文档
    

    根据国家进行分组
    // regroup cities|dictsort:”country” by country as country_list //

    - **ifequal** 如果相等
    - **ifnoequal** 如果不等
    - **ifchanged** 如果改变 
    
    // for date in days //
      // ifchanged date.date // {*{ date.date }} // endifchanged //
      // ifchanged date.hour date.date //
         {*{ date.hour }}
      // endifchanged //
    // endfor // 
    
    - **布尔操作** 详细文档(优先级由低到高) 
    
    1. or
    2. and
    3. not
    4. in
    5. ==、 !=、 >、 >=、 < <=
    
    - **// include 其他模板 //**
    

    // include “foo/bar.html” //
    传递参数
    // include “name_snippet.html” with person=”Jane” greeting=”Hello” //

    - **// ssi 本地文件 //** 详细文档
    - **url**
    

    第一个参数是 view 函数的路径,格式是 package.package.module.function 之后的参数使用 / 连接
    范例
    // url ‘path.to.view’ arg arg2 as the_url //

    <a href="{*{ the_url }}">I'm linking to {*{ the_url }} 
    

    可以使用过滤器,但大部分过滤器都返回字符串结果

    // if athlete_list|length > 1 //
         Team: // for athlete in athlete_list // ... // endfor //
      // else //
         Athlete: {*{ athlete_list.0.name }}
      // endif // 
    
    • 继承

    // block 名称 // … // endblock //
    // extends “base.html” // 必须第一行
    // block title //My amazing blog// endblock //
    {*{ block.super }} 引用父模版的内容 // block 名称 // … // endblock 名称 // 方便阅读

    五、form表单

    第一部分:定义

    可以使用两种方式

    • 自己定义 详细文档

    from django import forms

    class ContactForm(forms.Form):

    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)

    • 继承model 详细文档

    from django.forms import ModelForm

    有定义模块

    class Article(models.Model):

    headline = models.CharField(max_length=200)

    sites = models.ManyToManyField(Site)

    class ArticleForm(ModelForm):

    class Meta: 
    
    model = Article 
    

    第二部分:显示

    在把form表单和模板进行结合之前,先要知道如何处理提交的表单。

    • (预备知识) 在view中的标准处理form的框架

    from django.shortcuts import render
               from django.http import HttpResponseRedirect
    
               def contact(request):
                   if request.method == 'POST': # 表单被提交
                       form = ContactForm(request.POST) # 表单绑定了post数据
                       if form.is_valid(): # 所有的表单验证通过
                           # 对数据进行一些处理
                           # ...
                           return HttpResponseRedirect('/thanks/') # 转向或者其他操作
                   else:
                       form = ContactForm() # 没有提交的表单
    
                   return render(request, 'contact.html', {
                       'form': form,
                   }) 
    

    • 统一显示
    - form.as_p

    包围,分行显示

    - form.as_table        生成表格
    - form.as_ul        生成列表项
    
    # 实际的模板例子(contact.html)
               <form action="/contact/" method="post">// csrf_token //
               {*{ form.as_p }}
               <input type="submit" value="Submit" />
               </form> 
    
    • 单独自定义显示 详细文档
    <div class="fieldWrapper">
                   {*{ form.subject.errors }}
                   <label for="id_subject">Email subject:</label>
                   {*{ form.subject }}
               </div> 
    
    • 引用字段

    {*{ form.字段名 }}

    • 引用字段验证错误

    {*{ form.字段名.errors}}

    第三部分:验证

    详细文档 分为多个层次,检测失败会返回 ValidationError

    1. to_python()     [forms.Field] 转换成python的类型 使用范例
    2. validate()      [forms.Field] 针对特别字段验证,又不想放到验证器当中,不返回值
    3. run_validators()   运行所有字段级别验证,收集错误,不需要改写
    4. 字段级别clean()  调用上面3项验证,一旦有错,验证停止,否则返回 clean data 字典
    5. 表单级别clean_()  验证特别的字段
    6. 表单级别clean()  负责整个表单的验证,手工返回 self.cleaned_data
    • form组件自身的验证

    默认django会自动对form组件的post内容根据定义的类型进行验证,如果需要自定义,需要在 forms.Field 中定义。

    范例(上面的ContactForm为例):

    data={‘bookid’:’aa’,’days’:datetime.datetime.now(),’subject’:’ehllo’}
    f=ContactForm(data)
    f.is_valid()
    False
    f.errors
    {‘bookid’: [u’Enter a whole number.’]}

    • 定义Field子类进行验证

    使用 to_python() 和 validate() 的例子

    假设需要定义一个多邮件的组合字段,用逗号分隔邮件地址


    from django import forms
               from django.core.validators import validate_email
    
               class MultiEmailField(forms.Field):
                   def to_python(self, value):
                       "Normalize data to a list of strings."
    
                       # Return an empty list if no input was given.
                       if not value:
                           return []
                       return value.split(',')
    
                   def validate(self, value):
                       "Check if value consists only of valid emails."
    
                       # Use the parent's handling of required fields, etc.
                       super(MultiEmailField, self).validate(value)
    
                       for email in value:
                           validate_email(email) 
    

    • form内针对字段的验证
    举一个验证 recipients 字段必须包含 fred@example.com 项目
    

    class ContactForm(forms.Form):
                   # Everything as before.
                   ...
    
                   def clean_recipients(self):
                       data = self.cleaned_data['recipients']
                       if "fred@example.com" not in data:
                           raise forms.ValidationError("You have forgotten about Fred!")
    
                       # Always return the cleaned data, whether you have changed it or
                       # not.
                       return data 
    

    • form表单的组合验证
    如果我们有个需求需要验证比如密码和重复密码是否相同的话。这样验证单个字段的方法就没有用了,需要form的 clean()方法
    

    class ContactForm(forms.Form):
                   # Everything as before.
                   ...
    
                   def clean(self):
                       cleaned_data = super(ContactForm, self).clean()
                       password = self.cleaned_data.get('password', '').strip()
                       password1 = self.cleaned_data.get('password1','').strip()
                       if password and password1 and  password != password1:
                           msg = u'两次密码输入不一致'
                           self._errors["password1"] = ErrorList([msg])
                           del self.cleaned_data["password1"]
                       return self.cleaned_data 
    

    第四部分:访问 clean的数据

    表单的Post数据如果通过了验证,就叫做cleaned数据,被存放在 Form.cleaned_data字典中。

    data={‘bookid’:’12’,’days’:datetime.datetime.now(),’subject’:’ehllo’}
    f=ContactForm(data)
    f.is_valid()
    True
    f.cleaned_data
    {‘bookid’: 12, ‘days’: datetime.date(2013, 6, 16), ‘subject’: u’ehllo’}
    f.cleaned_data[‘days’]
    datetime.date(2013, 6, 16)

    六、model

    主页url文档 一个model类表示一个数据表,一个类的实例代表表中的记录

    第一部分:定义

    字段的命名不能包括两个下划线 
    
    • 简单的例子
    from django.db import models
    
               class Person(models.Model):
                   first_name = models.CharField(max_length=30)
                   last_name = models.CharField(max_length=30) 
    
    • 字段类型

    类型清单 BooleanField、CharField(max_length=None)…
    自定义新类型

    • 通用参数
    - null     默认False
    - blank     默认False ,True 字段允许为空
    - default    默认值,也可是可调用的对象
    - help_text   
    - primary_key   True,会把当前字段当成主键
    - unique   True, 表示唯一
    - verbose_name   字段名字
    - choices    选择 ,使用 **get_字段名称_desplay()** 显示内容
    

    from django.db import models
    
                           class Person(models.Model):
                               SHIRT_SIZES = (
                                   ('S', 'Small'),
                                   ('M', 'Medium'),
                                   ('L', 'Large'),
                               )
                               name = models.CharField(max_length=60)
                               shirt_size = models.CharField(max_length=1, 
                                                             choices=SHIRT_SIZES)
    
    
                           # 使用 choice的例子
                           >>> p = Person(name="Fred Flintstone", shirt_size="L")
                           >>> p.save()
                           >>> p.shirt_size
                           u'L'
                           >>> p.get_shirt_size_display()
                           u'Large'
    
                           # 使用 enumerate 生成choice的例子
                           # 和上面的定义作用类似
                           SHIRT_SIZES = enumerate(("Small","Medium", "Large")) 
    

    • 关系
    - ForeignKey     详细文档
    

    引用未定义     ‘’字符串
    递归         ‘self’

    - ManyToManyField   详细文档 使用范例
    - OneToOneField     
    
    • 元数据
    - ordering           顺序
    - db_table            数据库名称
    - verbose_name         对象名称
    - verbose_name_plural     复数对象名称  
    

    详细清单

    class Ox(models.Model):
                               horn_length = models.IntegerField()
    
                               class Meta:
                                   ordering = ["horn_length"]
                                   verbose_name_plural = "oxen" 
    
    • 模型方法
    - property           属性 
    
    def _get_full_name(self):
          "Returns the person's full name."
          return '%s %s' % (self.first_name, self.last_name)
          full_name = property(_get_full_name) 
    
    - __unicode__()        文本格式显示对象
    - get_absolute_url()        返回对象的url地址 详细文档
    - save()        保存
    - delete()        删除
    

    第二部分:查询

    文档 范例的model定义

    • 建立实体(记录)

    用字典作为参数实例化一个model类,然后 save() 保存。

    b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
                   b.save() 
    
    • 修改记录
    普通model,首先用 get() 等方法检索一个实体对象,修改属性,然后 save() 保存。 
    
    - 更新外键 ForeignKey
    

    e=Entry(headline=’headline’,body_text=’aaa’,
    pub_date=datetime.datetime.now(),
    mod_date=datetime.datetime.now(),
    n_comments=12,n_pingbacks=3,
    rating=5)
    e.blog=b
    e.save()

    • 更新ManyToManyField

    joe=Author(name=’bbb’,email=’aaa@test.com’)
    joe.save()
    e.authors.add(joe)

    # 另外一种方法建立
    

    newjoe=Author.objects.create(name=’John’)
    newjoe.save()
    e.authors.add(newjoe)

    # 同时增加多个对象关系
    

    entry.authors.add(john, paul, george, ringo)

    • 普通检索记录

    QuerySet     检索集合结果,也可以看成是数据对象的集合,
              可以有0-n个过滤器(filter)
    Manager     每个model都至少有一个Manager,默认名称是 objects

    # 获取所有记录
                           >>> all_entries = Entry.objects.all() 
    
    • 使用过滤器
    - filter     包含匹配
    - exclude    不包含匹配
    

    # 过滤年
                           >>>Entry.objects.filter(pub_date__year=2006)
    
                               # 连续串联过滤
                               # 所有headline满足What开头,出版时间在2005年1月30至今
                           >>> Entry.objects.filter(
                                   headline__startswith='What'
                               ).exclude(
                                   pub_date__gte=datetime.date.today()
                               ).filter(
                                   pub_date__gte=datetime(2005, 1, 30)
                               ) 
    

    • 使用get获得单个对象
    没有结果会报 DoesNotExist ,多个结果报 MultipleObjectsReturned 
    

    one_entry = Entry.objects.get(pk=1)

    # 结果切片 
    

    Entry.objects.all()[5:10]

    • 查找类型     Lookups 完整列表
    - exact     精确匹配 
    
    Entry.objects.get(id__exact=14) 
    
    - iexact     不区分大小写匹配 
    
    Blog.objects.get(name__iexact='beatles blog') 
    
    - contains     区分大小写包含
    - icontains     不区分大小写包含
    - startswith     开始
    - endswith      结束
    - in         在列表内 
    
    Entry.objects.filter(id__in=[1, 3, 4])
           # 动态生成列表
      inner_qs = Blog.objects.filter(name__contains='Cheddar')  
      entries = Entry.objects.filter(blog__in=inner_qs) 
    
    • pk
    可以使用 pk 作为主键进行检索 get(id__exact=14) (id=14) (pk=14)效果相同。 
           # 一些例子
    

    Blog.objects.filter(pkin=[1,4,7])
    Blog.objects.filter(pk
    gt=14)

    • 跨越关系检索记录
    1. 双下划线能够扩展到相关的model字段 范例模型
    
    # 检索 Entry --> blog --> name 是 "Beatles Blog"
    

    Entry.objects.filter(blognameexact=’Beatles Blog’)

    # pk的跨越关系检索
    

    Entry.objects.filter(blog__pk=3)

    2. 双下划线加上**小写的 model 名**,可以反方向引用 
    
    # 反向检索 Blog --> entry --> headline 包含 'Lennon'
    

    Blog.objects.filter(entryheadlinecontains=’Lennon’)

    • 使用 F()表达式 进行检索

    可以对同一个model的不同字段进行比较、计算(加减乘除)

    from django.db.models import F

        # 检索Entry中 n_comments 数值比 n_pingbacks 的记录
    >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
    
        # (计算范例) n_comments 数值比 n_pingbacks 多两倍的记录
    >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
    
        # (使用双下划线跨越关系和F()类的例子) 
        # 所有 authors的name 与 blog的name相同
    >>> Entry.objects.filter(authors__name=F('blog__name')) 
    
    • 使用 Q类 进行复杂检索

    filter进行筛选,组合条件都是AND关系,使用Q对象能进行 OR 关系组合条件。

    Q 实例是筛选条件的封装, | OR & 与

    from django.db.models import Q
      Q(question__startswith='What')
    
      Poll.objects.get(
          Q(question__startswith='Who'),
          Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
         ) 
    

    第三部分:其他操作

    • 比较记录对象

    some_obj == other_obj

    • 删除记录对象

    默认情况下以该对象为主键的对应记录被删除 >>>Entry.objects.filter(pub_date__year=2005).delete()

    • 拷贝记录对象

    把 pk 设为None,然后保存

    >>>blog = Blog(name='My blog', tagline='Blogging is easy')
           >>>blog.save() # blog.pk == 1
    
           >>>blog.pk = None
           >>>blog.save() # blog.pk == 2 
    
    • 一次更新多条记录

    update()

    >>>Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') 
    
    • 引用关联对象
    e(Entry) --> blog属性 
    

    e.blog

    _set     反向引用 b(Blog) —> Entry

    >>>>     
     >>>b.entry_set.all() 
    

    select_related()     递归取得关联数据,进入cache

    >>>>     
     >>> e = Entry.objects.select_related().get(id=2)
            >>> print(e.blog)  # 直接使用缓存 
    
    文章目录
    1. 1. 一、settings
    2. 2. 二、url conf
    3. 3. 三、view
    4. 4. 四、模板
    5. 5. {*{ story.headline|upper }}
    6. 6. 五、form表单
  • 有定义模块
    1. 1. 六、model