Django官方文档学习笔记

                                                    Django官方文档笔记

文章开始把我喜欢的这句话送个大家:这个世界上还有什么比自己写的代码运行在一亿人的电脑上更酷的事情吗,如果有那就是让这个数字再扩大十倍

1.函数 include() 允许引用其它URLconfs。每当Django 遇到:func~django.urls.include 时,它会截断与此项匹配的URL 的部分,并将剩余的字符串发送到URLconf 以供进一步处理。

我们设计 include() 的理念是使其可以即插即用。因为投票应用有它自己的URLconf( polls/urls.py ),他们能够被放在"/polls/" "/fun_polls/" "/content/polls/",或者其他任何路径下,这个应用都能够正常工作。

何时使用 include()

当包括其它URL 模式时你应该总是使用 include()  admin.site.urls 是唯一例外。

 

想在myapp中定一个主,然后通"http://localhost:8000/myapp/homepage"访问,首先我myproject/myapp//view.py中定一个叫homePage的函数(名字随意,不一定叫名字):

 

然后在myproject/myproject/urls.pyurlpatterns列表中添加一个url配置:

 

然后运行目,就可以用浏览器通http://localhost:8000/myapp/homepage访问

但假如一个project中有多个app,用以上的方式来管理url可能会造成比较混乱的局面,为了解决这个问题,我们可以用include的方法来配置url,

首先我们在自己的app中建立一个urls.py,即myproject/myapp/目录下建立urls.py,然后在其中输入如下内容:

 

然后在目的urls包含刚刚app中添加的url配置,我要做的是在myproject/myproject/urls.py输入如下内容:

 

 

2.编辑 mysite/settings.py 文件前,先设置 TIME_ZONE 为你自己时区。

此外,关注一下文件头部的 INSTALLED_APPS 设置项。这里包括了会在你项目中启用的所有Django 应用。应用能在多个项目中使用,你也可以打包并且发布应用,让别人使用它们。

通常, INSTALLED_APPS 默认包括了以下Django 的自带应用:

这些应用被默认启用是为了给常规项目提供方便。

python manage.py migrate

这个 migrate 命令检查 INSTALLED_APPS 设置,为其中的每个应用创建需要的数据表,至于具体会创建什么,这取决于你的 mysite/settings.py 设置文件和每个应用的数据库迁移文migrate 命令只会 INSTALLED_APPS 里声明了的行数据迁移。

如果你不需要某个或某些用,你可以在运行 migrate 前毫无顾虑地从 INSTALLED_APPS 里注或者除掉它

mysite/settings.py

INSTALLED_APPS =[

    'polls.apps.PollsConfig',//自己添加的应用要添加到setting文件中所有应用都在.apps

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

]

你模型的迁移数据,它被存在 polls/migrations/0001_initial.py 里。

迁移是非常强大的功能,它能让你在开发过程中持续的改变数据库结构而不需要重新删除和创建表它专注于使数据库平滑升级而不会丢失数据。我们会在后面的教程中更加深入的学习这部分内容,现在,你只需要记住,改变模型需要这三步:

3.创建一个管理员账

$ python manage.py createsuperuser

$ python manage.py runserver

进入管理站点页

现在,试着使用你在上一步中创建的超级用户来登录。然后你将会看到Django 管理页面的索引页:

向管理面中加入投票(某某)

但是我们的投票应用在哪呢?它没在索引页面里显示。

只需要做一件事:我们得告诉管理页面,问题 Question 对象需要被管理。打开 polls/admin.py 文件,把它编辑成下面这样:

from django.contrib import admin
from .models import Question
admin.site.register(Question)

 

4.polls/urls.py

fromdjango.urlsimportpath

from.importviews

urlpatterns =[

    # ex: /polls/

   path('', views.index, name='index'),

    # ex: /polls/5/

   path('<int:question_id>/', views.detail, name='detail'),

    # ex: /polls/5/results/

   path('<int:question_id>/results/', views.results, name='results'),

    # ex: /polls/5/vote/

   path('<int:question_id>/vote/', views.vote, name='vote'),

]

5.模板

 模板命名空间

虽然我们现在可以将模板文件直接放在  polls/templates 文件夹中(而不是再建立一个 polls 子文件夹),但是这样做不太好。Django 将会选择第一个匹配的模板文件,如果你有一个模板文件正好和另一个应用中的某个模板文件重名,Django 没有办法 区分 它们。我们需要帮助Django 选择正确的模板,最简单的方法就是把他们放入各自的 命名空间 中,也就是把这些模板放入一个和 自身 应用重名的子文件夹里。

「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程。于是Django 提供了一个快捷函数,我们用它来重写  index() 视图:

polls/views.py

fromdjango.shortcutsimportrender

from.modelsimportQuestion

defindex(request):

   latest_question_list =Question.objects.order_by('-pub_date')[:5]

   context ={'latest_question_list': latest_question_list}

    returnrender(request, 'polls/index.html', context)

 

抛出404 错误

现在,我们来处理投票详情视图——它会显示指定投票的问题标题。下面是这个视图的代码:

polls/views.py

from django.http import Http404
from django.shortcuts import render
from .models import Question
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

一个快捷函数: get_object_or_404()

尝试用 get() 函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程。Django 也提供了一个快捷函数,下面是修改后的详情 detail() 视图代码:

polls/views.py

fromdjango.shortcutsimportget_object_or_404, render

from.modelsimportQuestion

defdetail(request, question_id):

   question =get_object_or_404(Question, pk=question_id)

    returnrender(request, 'polls/detail.html', {'question': question})

去除模板中的硬编码URL

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

使用  {% url %}        标签代替编码

这个标签的工作方式是在 polls.urls 模块的URL 定义中寻具有指定名字的条目。你可以回忆一下,具有名字'detail' URL 是在如下语句中定义的:

# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),

如果你想改变投票详情视图的URL,比如想改成 polls/specifics/12/ ,你不用在模板里修改任何东西(包括其它模板),只要在 polls/urls.py 里稍微修改一下就行:

# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),

URL 名称添加命名空

polls/urls.py

fromdjango.urlsimportpath

from.importviews

app_name='polls'

urlpatterns =[

   path('', views.index, name='index'),

   path('<int:question_id>/', views.detail, name='detail'),

   path('<int:question_id>/results/', views.results, name='results'),

   path('<int:question_id>/vote/', views.vote, name='vote'),

]

修改为指向具有命名空间的详细视图:

polls/templates/polls/index.html

<li><ahref="{%url'polls:detail'question.id%}">{{question.question_text}}</a></li>

 

6.表单

  • 由于我们创建一个POST 表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造。Django 已经拥有一个用来防御它的非常容易使用的系统。简而言之,所有针对内部URL 的POST 表单都应该使用  {% csrf_token %} 模板标签。
  • 每个单选按钮的 name 是 "choice" 。这意味着,当有人选择一个单选按钮并提交表单提交时,它将发送一个POST 数据 choice=# ,其中# 为选择的Choice 的ID。这是HTML 表单的基本概念。

 action  {% url 'polls:vote' question.id %} ,并  method="post" 。使用 method="post"无论何时,当你需要创建一个改变服务器端数据的表单时,请使用 ``method="post" 

return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

在增加Choice 的得票数之后,代码返回一个 HttpResponseRedirect 而不是常用的 HttpResponse  HttpResponseRedirect 只接收一个参数:用户将要被重定向的URL(请继续看下去,我们将会解释如何构造这个例子中的URL)。

在这个例子中,我们在 HttpResponseRedirect 的构造函数中使用 reverse() 函数。这个函数避免了我们在视图函数中硬编码URL。它需要我们给出我们想要跳转的视图的名字和该视图所对应的URL 模式中需要给该视图提供的参数。在本例中,使用在 教程第部分 中设定的URLconf reverse() 调用将返回一个这样的字符串:

'/polls/3/results/'

使用通用视图

根据URL 中的参数从数据取数据、入模板文件然后返回渲染后的模板

改良URLconf

polls/urls.py

fromdjango.urlsimportpath

from.importviews

app_name ='polls'

urlpatterns =[

   path('', views.IndexView.as_view(), name='index'),

   path('<int:pk>/', views.DetailView.as_view(), name='detail'),

   path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),

   path('<int:question_id>/vote/', views.vote, name='vote'),

]

注意,第二个和第三个匹配准中,路径字符串中匹配模式的名称已经由 <question_id>  <pk>

改良视图

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'
    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]

使用基于视图

从本质上讲,基于类的视图允许您使用不同的类实例方法响应不同的HTTP请求方法,而不是在单个视图函数中使用条件分支代码。

那么在GET视图函数中处理HTTP的代码看起来像这样:

fromdjango.httpimportHttpResponse

defmy_view(request):

    ifrequest.method =='GET':

       # <view logic>

       returnHttpResponse('result')

在基于类的视图中,这将变为:

fromdjango.httpimportHttpResponse

fromdjango.viewsimportView

classMyView(View):

    defget(self, request):

       # <view logic>

       returnHttpResponse('result')

DjangoURL解析器期望将求和关的参数送到可用的函数而不是,所以基于视图具有 as_view()类方法,该类方法返回当请求到达匹配关联模式的URL时可以调用的函数该函数创建类的实例并调用dispatch()方法。dispatch查看请求以确定它是否为GETPOST等等,并将求中到匹配方法(如果已定),或者HttpResponseNotAllowed如果不是 

# urls.py
from django.urls import path
from myapp.views import MyView
urlpatterns = [
    path('about/', MyView.as_view()),
]

值得注意的是,您的方法返回的内容与从基于函数的视图返回的内容相同,即某种形式的 HttpResponse。这意味着http快捷方式 TemplateResponse对象在基于类的视图中有效。

虽然最小的基于类的视图不需要任何类属性来执行其工作,但类属性在许多基于类的设计中很有用,并且有两种方法来配置或设置类属性。

 

总结:

 1.reverse() :个例子中,我 HttpResponseRedirect 的构造函数中使用 reverse() 函数。个函数避免了我视图函数中硬编码URL。

2.render() (:「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程。

3.as_view():基于类的视图返回

4.generic :通用视图

 

 

 

 

Django 的源文件在哪里?

如果你不知道Django 源码在你系统的哪个位置,运行以下命令:

$ python -c "import django; print(django.__path__)"

所有的Django 后台模板均可被复写。若要复写模板,像你修改 base_site.html 修改其它文件——先将其从默中拷到你的自定,再做修改。

 

models

1.字段选项

null如果TrueDjangoNULL在数据中存。默False

blank如果True,该字段允许为空。默认是False

请注意,这不同于null null纯粹与数据库相关,而 blank与验证相关。如果字段有 blank=True,则表单验证将允许输入空值。如果字段有blank=False,则需要该字段

一关系

要定义多对一关系,请使用django.db.models.ForeignKey。您可以像使用任何其他Field类型一样使用它:将其包含为模型的类属性

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)   //manufacturer为car的外键,一个car一个manufacturer,一个manufacturer多个car

多关系

class Topping(models.Model):
    pass
class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

一般情况,普通的多多已经够用,无需自己建第三关系表。但是某些情况可能更复一点,比如如果你想保存外字段信息,例如:某个人加入某个分时间呢?想保存进组的原因呢?-----中表。与普通的多多不一,使用自定表的多多不能使用add(), create(),remove(),set()方法来建、除关系为什么?因为上面的方法无法提供加入时间、邀请原因等中间模型需要的字段内容。唯一的办法只能是通过创建中间模型的实例来创建这种类型的多对多关联。但是,clear()方法是有效的,它能清空所有的多对多关系。

 

book = person.book_set.all()//person book 一对多
django 默认每个主表的对象都有一个是外键的属性,可以通过它来查询到所有属于主表的子表的信息。
这个属性的名称默认是以子表的名称小写加上_set()来表示,默认返回的是一个querydict对象,你可以继续的根据情况来查询等操作。
在实际项目中,我们使用最多的还是related_name
如果你觉得上面的定义比较麻烦的话,你也可以在定义主表的外键的时候,给这个外键定义好一个名称。要用related_name比如在Book表中:  //book表中定义ForeignKey为主表名
  person = models.ForeignKey(Person, related_name='person_books')
那么实现上面的需求,可以使用person.book_set.all()也可以使用person.person_books.all()
 
 

在使用中模型定从模型到自身的多多关系使用 symmetrical=False

模型方法和属性

__str__()

Python“方法,返回任何象的字符串表示形式

get_absolute_url()

这告诉Django如何计算对象的URLDjango在其管理界面中使用它,并且只要它需要找出对象的URL。具有唯一标识它的URL的任何对象都应定义此方法。

模型最重要的属性是 Manager。默名称 objects。管理只能通模型​​类访问,而不能通模型​​访问

 

Django中有三种可能的继承方式。

  1. 通常,您只想使用父来保存您不希望每个子模型入的信息。不会被孤立使用,所以抽象基就是你所追求的。它不生成数据表或具有管理器,并且无法直接例化或保存。
  2. 如果你是现有模型的子类(可能是完全来自另一个应用程序的东西),并希望每个模型都有自己的数据库表,那么 多表是最佳选择。
  3. 最后,如果您只想修改模型的Python级行为,而不以任何方式更改模型字段,则可以使用 代理模型

 

  1. 创建和保存对象,请使用该 create()方法

b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
   b.save()

2.更新ManyToManyField工作的方式略有不同

entry.authors.add(john, paul, george, ringo)//add方法可一次性添加多个

3.filter(**kwargs)返回QuerySet包含与找参数匹配的新象。

exclude(**kwargs)返回QuerySet包含与找参数匹配的新

Entry.objects.filter( headline__startswith='What').exclude(
   pub_date__gte=datetime.date.today()).filter(
 pub_date__gte=datetime.date(2005, 1, 30) )

 

manager

4.filter()QuerySet即使只有一个象与查询匹配,它总会给你一个 - 种情况下,它将 QuerySet包含一个元素。如果您知道只有一个象与您的查询匹配,可以使用直接返回象的 get()方法 Manager

 

基本找关字参数采用表field__lookuptype=value。(是一个双重下划线

Entry.objects.filter(pub_date__lte='2006-01-01')

将(粗略地)翻译成以下SQL

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

但是有一个例外,如果ForeignKey你可以指定后缀的字段名称_id。在这种情况下,value参数应包含外部模型主键的原始值。例如:

>>> Entry.objects.filter(blog_id=4)

果您的关键字参数不包含双下划线则假定查找类型为 exact

例如,以下两个语句是等效的:

>>> Blog.objects.get(id__exact=14)  # Explicit form
>>> Blog.objects.get(id=14)  
iexact不区分大小写的匹配项

contains

还有一个不区分大小写的版icontains

跨越关系的找:双下划线

Blog.objects.filter(entry__headline__contains='Lennon')

跨越多关系

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

过滤器可以引用模型上的字

from django.db.models import F

请注意,这delete()是唯一 QuerySet未在Manager自身上公开的方法 。这是一种安全机制,可以防止您意外请求Entry.objects.delete()和删除所有条目。如果您确实要删除所有对象,则必须显式请求完整的查询集:

Entry.objects.all().delete()

使用自定反向管理器

默认情况下,RelatedManager用于反向关系的是 该模型的默认管理器的子类。如果要为给定查询指定其他管理器,可以使用以下语法:

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')
 
a = Author.objects.get(id=5)

a.entry_set.all()# Returns all Entry objects for this Author.//反向模型使用原始模型的小写模型名称,加上'_set'(就像反向一多关系一

视图

1.使用register_converter()以下命令在URLconf中注册自定义转换器类 

from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
//class FourDigitYearConverter
urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<yyyy:year>/', views.year_archive),
]

2.如果路径和转换法不足以定URL模式,则还可以使用正表达式。使用 re_path()而不是path()

3.urlpatterns=[

    path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]

在这个例子中,对于请求/blog/2005/Django将调用 views.year_archive(request, year=2005,foo='bar')

联合框架

fromdjango.contrib.syndication.viewsimportFeed

 

4.Django提供了不同的层级的url逆向处理工具:

             1.在模板templates中,使用url标记,如:{% url %}

             2.Python代码中,使用django.core.urlresolvers.reverse()方法

             3.在更高一层级的处理url中,用get_absolute_url()方法

   需求点击博客的继续阅读加载全文

5.自定义错误视图

只需在URLconf中指定理程序,如下所示(在其他地方置它将无效

page_not_found()视图由重写 handler404

handler404 = 'mysite.views.my_custom_page_not_found_view'

django.views.decorators.http可用于根据求方法限制对视图访问django.http.HttpResponseNotAllowed如果不足条件,这些装饰器将返回a 

 

 

例如,考虑应用程序跟踪音乐家所属的音乐组的情况。一个人与他们所属的团体之间存在多对多的关系,因此您可以使用ManyToManyField来表示这种关系。但是,您可能希望收集的成员资格有很多详细信息,例如此人加入该组的日期。

对于这些情况,Django允许您指定将用于管理多对多关系的模型。然后,您可以在中间模型上添加额外的字段。中间模型与ManyToManyField使用 through参数指向将充当中介的模型相关联 。对于我们的音乐家示例,代码看起来像这样:

from django.db import models
class Person(models.Model):
    name = models.CharField(max_length=128)
    def __str__(self):
        return self.name
class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')
    def __str__(self):
        return self.name
class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)
 

简单文件上

请注意只有在请求是通过 POST 提交且提交的 <form>  enctype="multipart/form-data" 属性的候,request.FILES 才会包含文件数据,否 request.FILES 是空的。

forms.py

fromdjangoimportforms

classUploadFileForm(forms.Form):

   title =forms.CharField(max_length=50)

   file =forms.FileField()

 

views.py

fromdjango.httpimportHttpResponseRedirect

fromdjango.shortcutsimportrender

from.formsimportUploadFileForm

 

# Imaginary function to handle an uploaded file.

fromsomewhereimporthandle_uploaded_file

 

defupload_file(request):

    ifrequest.method =='POST':

        form =UploadFileForm(request.POST, request.FILES)#//注意我向表的构造器中传递request.FILES是文件数据定到表的方法。

 

       ifform.is_valid():#有效的

           handle_uploaded_file(request.FILES['file'])#读取处理文件函数

           returnHttpResponseRedirect('/success/url/')

    else:

       form =UploadFileForm()

    returnrender(request,'upload.html', {'form': form})

 

FILES是个字典,它包含每个FileField(或者 ImageFieldFileField的子)。这样就可以用request.FILES['file']来存放表中的些数据了。

当用户上传一个文件的时候,Django会把文件数据传递给上传处理器– 一个小型的类,会在文件数据上传时处理它。上传处理器在FILE_UPLOAD_HANDLERS中定义,默认为:

("django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler",)

MemoryFileUploadHandler TemporaryFileUploadHandler一起提供了Django的默认文件上传行为,将小文件读取到内存中,大文件放置在磁盘中。

 

get_absolute_url() 

reverse()

redirect()

 

 

django 中的中件(middleware),在django中,中件其就是一个,在求到来和束后,django会根据自己的规则在合适的行中件中相的方法。

中间件中一共有四个方法:

process_request  process_view   process_exception   process_response

django中叫中件,在其他web框架中,有的叫管道,httphandle

我们可以自己写一个类,但是必须继承MiddlewareMixin

所以需要导入:from django.utils.deprecation import MiddlewareMixin

 

 

 

加油吧,程序员!

猜你喜欢

转载自blog.csdn.net/weixin_42248302/article/details/85368848