Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1738972
  • 博文数量: 410
  • 博客积分: 9563
  • 博客等级: 中将
  • 技术积分: 4517
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-03 19:59
个人简介

文章分类

全部博文(410)

文章存档

2017年(6)

2016年(1)

2015年(3)

2014年(4)

2013年(32)

2012年(45)

2011年(179)

2010年(140)

分类: Web开发

2013-06-18 19:31:33


django的调度逻辑图

目录

一、settings

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

二、url conf

  • urlpatterns 是所有url的链表,可以 +=

     from django.conf.urls import patterns, include, url
       urlpatterns = patterns('',)
       urlpatterns += patterns('',
           url(r'^tag/(?P\w+)/$', 'tag'),) 
  • 可以使用 include来引用 app内部urls.py文件

     url(r'^elist/', include('elist.urls')), 
  • url中引用参数

 在需要捕捉的地方用括号括起来  
   (r'homeworklist/edit/([^/]+)/$', edit_homeworklist),
   调用结果:edit_homeworklist(request,参数)

   命名参数 ?P
   (r'homeworklist/edit/(?P[^/]+)/$', 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\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(推荐使用)
  2. 传入一个url,进行跳转

    return redirect('/some/url/')
    return redirect('')

三、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 ,如果要使用 , 需要手工定义 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 %}
            

{{ section.title }}

{% 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模板
    • {% 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 %}

 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)
            {% csrf_token %}
            {{ form.as_p }}
            
             
 
{{ form.subject.errors }} {{ form.subject }}
  • 引用字段

    {{ 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

一个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类,然后 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] 
  • 查找类型     

    • 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(pk__in=[1,4,7])
           >>> Blog.objects.filter(pk__gt=14) 
  • 跨越关系检索记录

    1. 双下划线能够扩展到相关的model字段
       # 检索 Entry --> blog --> name 是 "Beatles Blog"
         >>> Entry.objects.filter(blog__name__exact='Beatles Blog')
             # pk的跨越关系检索
         >>> Entry.objects.filter(blog__pk=3) 
    2. 双下划线加上小写的 model 名,可以反方向引用
       # 反向检索 Blog --> entry --> headline 包含 'Lennon'
         >>> Blog.objects.filter(entry__headline__contains='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)  # 直接使用缓存 
阅读(3394) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~