一、简单演示

返回当前时间

url.py文件内容:

from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^timmer/', views.timmer),]

views.py文件内容:

from django.shortcuts import render,HttpResponse,redirectdef timmer(request):    import time    ctime=time.time()    # return HttpResponse (ctime)          #只能返回字符串    return render(request,"timmer.html", {"ctime":ctime})     #返回html,这样就能定义返回的样式

timmer.html文件内容:

    
    
timmer    < style >        p{        color: red;        }    {#双大括号是模板语法,里面是变量,接受views.py的参数#}

当前时间:{

{ ctime }}

二、url控制器

1、url的分组

urls.py文件内容:

from django.conf.urls import url,includefrom django.contrib import adminfrom django.shortcuts import HttpResponsefrom app01.views import *urlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^timer/$', timer),                                        # timer(request)    #分组    url(r'^books_achrive/(\d+)/$', book_detail),              # book_detail(request,3)    url(r'^books_achrive/(\d+)/(\d+)/$', books_achrive),        # books_achrive(request,2012,12)    #有名分组books_achrive后面有一个year组和一个month组    url(r'^books_achrive/(?P
\d+)/(?P
\d+)/$', books_achrive2), # books_achrive(request,year=2012,month=12)]

views.py文件内容:

from django.shortcuts import render,HttpResponse,redirectdef book_detail(reqeust,id):    return HttpResponse(id)    def books_achrive(request,year,month):    return HttpResponse(year+":"+month)    def books_achrive2(request,month,year):    return HttpResponse(year+":"+month)

这样用户访问的路径为/books_achrive/2012/12/时,就会在URL匹配到url(r'^books_achrive/(\d+)/(\d+)/$', books_achrive),然后执行books_achrive函数

2、url的分发

在项目下的urls.py文件里面定义连接到具体的应用的路径

url(r'^app01/', include('app01.urls'), ),

然后在具体应用的urls.py文件里面定义具体的url

from django.conf.urls import url,includefrom app01.views import *urlpatterns = [    url(r'^timer/$', timer), # timer(request)    url(r'^books_achrive/(\d+)/$', book_detail), # book_detail(request,3)    url(r'^books_achrive/(?P
\d+)/(?P
\d+)/$', books_achrive2), # books_achrive(request,year=2012,month=12)]

3、URL 的反向解析

在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。

人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。

换句话讲,需要的是一个DRY 机制。除了其它有点,它还允许设计的URL 可以自动更新而不用遍历项目的源代码来搜索并替换过期的URL。

在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

(1)在模板中:使用url 模板标签。

from django.conf.urls import urlfrom . import viewsurlpatterns = [        url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),]

在模板的代码中使用下面的方法获得它们:

2012 Archive
    {% for yearvar in year_list %}
  • {
    { yearvar }} Archive
  • {% endfor %}

(2)在Python 代码中:使用django.core.urlresolvers.reverse() 函数。

from django.core.urlresolvers import reversefrom django.http import HttpResponseRedirectdef redirect_to_year(request):    year = 2006.    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

(3)在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。

4、反向解析示例:登录页面

urls.py文件内容:

from django.conf.urls import url,includefrom django.contrib import adminfrom django.shortcuts import render,HttpResponse,redirectfrom app01.views import *urlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^login/', login,name="xxx"),     #定义url的别名xxx]

views.py文件内容:

from django.shortcuts import render,HttpResponse,redirectdef login(request):    if request.method=="GET":        print(request.GET)        print(request.POST)        print(request.method)        print(request.path)        print(request.path_info)        print(request.body)        return render(request, "login.html")    else:        user=request.POST.get("user")        pwd=request.POST.get("pwd")                if 1:                                    #用户输入的用户名和密码与数据库里面的做对比,判断是否一致            return redirect("/app01/timer/")

登录页面login.html文件内容:

    
    
Title    
    {% csrf_token %}                                  #解决出现Forbidden (403)错误    

用户名 

    

密码 

    

利用反向解析的好处:访问的时候用url的别名可以避免了随着url的变化而访问路径跟着变化

三、视图层之视图函数(views)

1、HttpRequest对象的属性

(1)HttpRequest.body

  一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。

  但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。

(2)HttpRequest.path

  一个字符串,表示请求的路径组件(不含域名)。

  例如:"/music/bands/the_beatles/"

(3)HttpRequest.method

  一个字符串,表示请求使用的HTTP方法。必须使用大写。

  例如:"GET"、"POST"

(4)HttpRequest.encoding

  一个字符串,表示提交的数据的编码方式(如果为None则表示使用DEFAULT_CHARSET的设置,默认为'utf-8')。

这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。

接下来对属性的任何访问(例如从GET或POST中读取数据)将使用新的encoding值。

如果你知道表单数据的编码不是DEFAULT_CHARSET ,则使用它。

(5)HttpRequest.GET

  一个类似于字典的对象,包含HTTP、GET的所有参数。详情请参考QueryDict对象。

(6)HttpRequest.POST

  一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成QueryDict对象。

  POST请求可以带有空的POST字典 —— 如果通过HTTPPOST方法发送一个表单,但是表单中没有任何的数据,QueryDict对象依然会被建。

因此,不应该使用 if request.POST来检查使用的是否是POST方法;应该使用 if request.method == "POST"

  另外:如果使用POST上传文件的话,文件信息将包含在FILES属性中。

(7)HttpRequest.REQUEST

  一个类似于字典的对象,它首先搜索POST,然后搜索GET,主要是为了方便。灵感来自于PHP的 $_REQUEST。

  例如,如果GET = {"name": "john"}而POST = {"age": '34'} , REQUEST["name"]将等于"john", REQUEST["age"]将等于"34"。

  强烈建议使用GET和POST而不要用REQUEST,因为它们更加明确。

(8)HttpRequest.COOKIES

  一个标准的Python字典,包含所有的cookie。键和值都为字符串。

(9)HttpRequest.FILES

  一个类似于字典的对象,包含所有的上传文件信息。

   FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。

  注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。

(10)HttpRequest.META

   一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:

    CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。

    CONTENT_TYPE —— 请求的正文的MIME 类型。

    HTTP_ACCEPT —— 响应可接收的Content-Type。

    HTTP_ACCEPT_ENCODING —— 响应可接收的编码。

    HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。

    HTTP_HOST —— 客服端发送的HTTP Host 头部。

    HTTP_REFERER —— Referring 页面。

    HTTP_USER_AGENT —— 客户端的user-agent 字符串。

    QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。

    REMOTE_ADDR —— 客户端的IP 地址。

    REMOTE_HOST —— 客户端的主机名。

    REMOTE_USER —— 服务器认证后的用户。

    REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。

    SERVER_NAME —— 服务器的主机名。

    SERVER_PORT —— 服务器的端口(是一个字符串)。

   从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,

    都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_  前缀。

    所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

(11)HttpRequest.user

  一个AUTH_USER_MODEL类型的对象,表示当前登录的用户。

  如果用户当前没有登录,user将设置为django.contrib.auth.models.AnonymousUser的一个实例。你可以通过is_authenticated()区分它们。

例如:

if request.user.is_authenticated():# Do something for logged-in users.else:    # Do something for anonymous users.

  

user 只有当Django启用AuthenticationMiddleware中间件时才可用。

(12)HttpRequest.session

      一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django启用会话的支持时才可用。

(13)HttpRequest.resolver_match

      一个ResolverMatch的实例,表示解析后的URL。这个属性只有在URL解析方法之后才设置,这意味着它在所有的视图中可以访问,

    但是在URL解析发生之前执行的中间件方法中不可以访问(比如process_request,但你可以使用process_view代替)。

四、MTV模型

Django的MTV分别代表:

       Model(模型):负责业务对象与数据库的对象(ORM)

       Template(模版):负责如何把页面展示给用户

       View(视图):负责业务逻辑,并在适当的时候调用Model和Template

       此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

1、模板层(template)

from django.conf.urls import url,includefrom django.contrib import adminfrom django.shortcuts import HttpResponsefrom app01.views import *urlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^template/', temp_func,),]

views.py文件内容:

def temp_func(request):    l=[11,222,333]    dic={"name":"yuan","age":23}        class Person(object):        def __init__(self,name,age):            self.name=name            self.age=age        def learning(self):             return "learning"    alex=Person("alex",45)    egon=Person("egon",36)    person_list=[alex,egon]        import datetime    now=datetime.datetime.now()    print(now)        file_size=234212123    content="hello yuan world text"    s="
hello"    #return render(request,"temp.html",{"l":l,"dic":dic})    return render(request,"temp.html",locals())

app01应用下创建templatetags模块(文件夹),里面创建my_filters_tags.py文件,内容如下:

@register.filterdef multi_filter(x,y):    return x * y@register.simple_tagdef multi_tag(x,y):    return x * y

temp.html文件内容:

{% load my_filters_tags %}    
    
Title

变量

{

{ l }}

                             {#  结果是:[11, 222, 333]    #}

{

{ l.1 }}

                           {#  结果是:222   #}

{

{ dic }}

                            {#  结果是:{'name': 'yuan', 'age': 23}   #}

{

{ dic.name }}

                       {#  结果是:yuan   #}

{

{ alex.age }}

                       {#  结果是:45   #}

过滤器

                           {#  语法;{
{obj|filter__name:param}}   #}

{

{ l.1|add:100 }}

                     {#  结果是:322   #}

{

{ now|date:"Y-m-d" }}

                 {#  结果是:2018-04-16   #}

{

{ file_size|filesizeformat }}

           {#  结果是:223.4 MB   #}

{

{ content|truncatechars:12 }}

           {#  结果是:hello yua...  加上点号一共显示12个字符 #}

{

{ content|truncatewords:2 }}

            {#  结果是:hello yuan ...  显示两个单词#}

{

{ content|slice:"2:-1" }}

              {#  结果是:llo yuan world tex  #}

{

{ s|safe }}

                        {#  结果是:hello   告诉Django这段代码是安全的不必转义#}

标签

{% for person in person_list %}                {#  for循环person_list列表   #}   

{

{ forloop.counter0 }} {
{ person.name }}:{
{ person.age }} --- {
{ person.learning }}

{% endfor %}{#  {
{ forloop.counter0 }} 可以取到循环序号  #}{#  如果变量l.0 > 100,就显示100,否则显示变量l.0    #}{% if l.0 > 100 %}    

100

 {% else %}    

{

{ l.0 }}

{% endif %}

自定义过滤器或者标签

{
{ l.0|multi_filter:2 }}                          {#  结果是:22   #}{% multi_tag l.0|add:12 10 %}                     {#  结果是:230   #}

五、Django-model基础

1、在settings.py配置下面内容可以查看翻译成的sql语句

LOGGING = {    'version': 1,    'disable_existing_loggers': False,    'handlers': {        'console':{            'level':'DEBUG',            'class':'logging.StreamHandler',        },    },    'loggers': {        'django.db.backends': {            'handlers': ['console'],            'propagate': True,            'level':'DEBUG',        },    }} 

2、创建模型

class Author(models.Model):                            #Author表包含 nid、name、age、 authorDetail字段    nid = models.AutoField(primary_key=True)    name = models.CharField(max_length=32)    age = models.IntegerField()    # 与AuthorDetail建立一对一的关系    authorDetail = models.OneToOneField(to="AuthorDetail")    class AuthorDetail(models.Model):                        #AuthorDetail表包含nid、birthday、telephone、addr字段    nid = models.AutoField(primary_key=True)    birthday = models.DateField()    telephone = models.BigIntegerField()    addr = models.CharField(max_length=64)    class Publish(models.Model):                             #Publish表包含nid、name、city、email字段    nid = models.AutoField(primary_key=True)    name = models.CharField(max_length=32)    city = models.CharField(max_length=32)    email = models.EmailField()    class Book(models.Model):                               #Book表包含nid、title、publishDate、price、keepNum、publish字段    nid = models.AutoField(primary_key=True)    title = models.CharField(max_length=32)    publishDate = models.DateField()    price = models.DecimalField(max_digits=5, decimal_places=2)    keepNum = models.IntegerField() < br > commentNum = models.IntegerField()    # 与Publish建立一对多的关系,外键字段建立在多的一方    publish = models.ForeignKey(to="Publish", to_field="nid")    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表    authors = models.ManyToManyField(to='Author') 

3、字段选项

(1)null

如果为True,Django将用NULL来在数据库中存储空值。 默认值是False.

(2)blank

如果为True,该字段允许不填。默认为False。要注意,这与null不同。null纯粹是数据库范畴的,而blank是数据验证范畴的。

如果一个字段的blank = True,表单的验证将允许该字段是空值。如果字段的blank = False,该字段就是必填的。

(3)default

字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。

(4)primary_key

如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key = True,Django就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key = True。

(5)unique

如果该值设置为True, 这个数据字段的值在整张表中必须是唯一的

(6)choices

由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。

4、添加表记录

(1)普通字段

    #1、方式1    publish_obj = Publish(name="人民出版社", city="北京", email="renMin@163.com")    publish_obj.save()  # 将数据保存到数据库    #2、方式2 < br > 返回值publish_obj是添加的记录对象    publish_obj = Publish.objects.create(name="人民出版社", city="北京",                                         email="renMin@163.com") < br > < br > 方式3 < br > 表.objects.create(**request.POST.dict())

(2)外键字段

    #1、方式1:    publish_obj = Publish.objects.get(nid=1)    Book.objects.create(title="西游记", publishDate="2012-12-12", price=665, pageNum=334, publish=publish_obj)    #2、方式2:    Book.objects.create(title="西游记", publishDate="2012-12-12", price=665, pageNum=334, publish_id=1) 

(3)多对多字段

    book_obj = Book.objects.create(title="追风筝的人", publishDate="2012-11-12", price=69, pageNum=314, publish_id=1)    author_yuan = Author.objects.create(name="yuan", age=23, authorDetail_id=1)    author_egon = Author.objects.create(name="egon", age=32, authorDetail_id=2)    book_obj.authors.add(author_egon, author_yuan)  # 将某个特定的 model 对象添加到被关联对象集合中。   =======    book_obj.authors.add(*[])    book_obj.authors.create()  # 创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。    解除关系:    book_obj.authors.remove()     # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])    book_obj.authors.clear()       #清空被关联对象集合。

5、查询表记录

(1)查询相关API

< 1 > all():                        查询所有结果

< 2 > filter(**kwargs):             它包含了与所给筛选条件相匹配的对象

< 3 > get(**kwargs):                返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

< 4 > exclude(**kwargs):            它包含了与所给筛选条件不匹配的对象

< 5 > values(*field):               返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

< 6 > values_list(*field):          它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

< 7 > order_by(*field):              对查询结果排序

< 8 > reverse():                    对查询结果反向排序

< 9 > distinct():                   从返回结果中剔除重复纪录

< 10 > count():                     返回数据库中匹配查询(QuerySet)的对象数量。

< 11 > first():                     返回第一条记录

< 12 > last():                      返回最后一条记录

< 13 > exists():                    如果QuerySet包含数据,就返回True,否则返回False

(2)双下划线之单表查询

models.Tb1.objects.filter(id__lt=10, id__gt=1)       # 获取id大于1 且 小于10的值models.Tb1.objects.filter(id__in=[11, 22, 33])      # 获取id等于11、22、33的数据models.Tb1.objects.exclude(id__in=[11, 22, 33])     # not inmodels.Tb1.objects.filter(name__contains="ven")models.Tb1.objects.filter(name__icontains="ven")   # icontains大小写不敏感models.Tb1.objects.filter(id__range=[1, 2])         # 范围bettwen andstartswith,istartswith, endswith, iendswith 

(3)基于对象的跨表查询

< 1 >一对多查询(Publish 与 Book)

正向查询(按字段:publish):# 查询nid=1的书籍的出版社所在的城市
book_obj=Book.objects.get(nid=1)
print(book_obj.publish.city) # book_obj.publish 是nid=1的书籍对象关联的出版社对象 反向查询(按表名:book_set):# 查询 人民出版社出版过的所有书籍publish = Publish.objects.get(name="人民出版社")book_list = publish.book_set.all()          # 与人民出版社关联的所有书籍对象集合for book_obj in book_list:    print(book_obj.title)

< 2 >一对一查询

正向查询(按字段:authorDetail):# 查询egon作者的手机号author_egon = Author.objects.get(name="egon")print(author_egon.authorDetail.telephone)反向查询(按表名:author):# 查询所有住址在北京的作者的姓名authorDetail_list = AuthorDetail.objects.filter(addr="beijing")for obj in authorDetail_list:    print(obj.author.name)

< 3 >多对多查询

正向查询(按字段:authors):book_obj = Book.objects.filter(title="西游记").first()authors = book_obj.authors.all()for author_obj in authors:    print(author_obj.name, author_obj.authorDetail.telephone)    反向查询(按表名:book_set):# 查询egon出过的所有书籍的名字author_obj = Author.objects.get(name="egon")book_list = author_obj.book_set.all()       # 与egon作者相关的所有书籍for book_obj in book_list:    print(book_obj.title)        #查询 人民出版社出版过的所有书籍publish = Publish.objects.get(name="人民出版社")book_list = publish.bookList.all()          # 与人民出版社关联的所有书籍对象集合

(4)基于双下划线的跨表查询

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)

    # 正向查询 按字段:publish    queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","price")        # 反向查询 按表名:book    queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__price")

# 练习2: 查询egon出过的所有书籍的名字(多对多)

    # 正向查询 按字段:authors:    queryResult=Book.objects.filter(authors__name="yuan").values_list("title")        # 反向查询 按表名:book    queryResult=Author.objects.filter(name="yuan").values_list("book__title","book__price")

# 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名

    # 正向查询    queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")        # 反向查询    queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")

# 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称

    queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151").values_list("title","publish__name")

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)

# 反向查询 不再按表名:book,而是related_name:bookList    queryResult = Publish.objects.filter(name="人民出版社").values_list("bookList__title", "bookList__price")

6、修改表记录

Book.objects.filter(price=123,title="python").update(title="python123")

7、删除表记录

Book.objects.filter(price=123,title="python").delete()你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。例如,下面的代码将删除 pub_date 是2005年的 Entry 对象:Entry.objects.filter(pub_date__year=2005).delete()

要牢记这一点:无论在什么情况下,QuerySet 中的 delete() 方法都只使用一条 SQL 语句一次性删除所有对象,而并不是分别删除每个对象。如果你想使用在 model 中自定义的 delete() 方法,就要自行调用每个对象的delete 方法。(例如,遍历 QuerySet,在每个对象上调用 delete()方法),而不是使用 QuerySet 中的delete()方法。

在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:b = Blog.objects.get(pk=1)# This will delete the Blog and all of its Entry objects.b.delete()