VUE计算属性定义：要用的属性不存在，要通过已有属性计算得来。原理：底层借助了Objcet.defineproperty方法提供的getter和setter。get函数什么时候执行？初次读取时会执行一次。当依赖的数据发生改变时会被再次调用。优势：与methods实现相比，内部有缓存机制（复用），效率更高，调试方便。备注：计算属性最终会出现在vm上，直接读取使用即可。如果计算属性要被修改，那必须写set函数去响应修改，且set中要引起计算时依赖的数据发生改变。 计算属性 {{ msg }} 监视属性监视属性watch：当被监视的属性变化时, 回调函数自动调用, 进行相关操作监视的属性必须存在，才能进行监视！！监视的两种写法：new Vue时传入watch配置通过vm.$watch监视深度监视：Vue中的watch默认不监测对象内部值的改变（一层）。配置deep:true可以监测对象内部值改变（多层）。 监视属性 {{ msg }} 条件渲染v-ifv-if="表达式"v-else-if="表达式"v-else="表达式"适用于：切换频率较低的场景。特点：不展示的DOM元素直接被移除。注意：v-if可以和:v-else-if、v-else一起使用，但要求结构不能被“打断”。v-show写法：v-show="表达式"适用于：切换频率较高的场景。特点：不展示的DOM元素未被移除，仅仅是使用样式隐藏掉使用v-if的时，元素可能无法获取到，而使用v-show一定可以获取到。 条件渲染 now id : {{ id }} v-if: {{ person_info[0] }} {{ person_info[1] }} {{ person_info[2] }} v-if v-else-if v-else: {{ person_info[0] }} {{ person_info[1] }} <p v-else>{{ person_info[2] }} v-show: {{ person_info[0] }} {{ person_info[1] }} {{ person_info[2] }} id++ 列表渲染列表基础v-for指令:用于展示列表数据语法：v-for="(item, index) in xxx" :key="yyy"可遍历：数组、对象、字符串（用的很少）、指定次数（用的很少） 列表渲染 遍历数组 index:{{index}} -- person:{{p}} 遍历对象 key:{{key}} -- value:{{value}} 遍历指定次数 index:{{index}} -- value:{{value}} 遍历字符串 index:{{index}} -- value:{{value}} 列表过滤watch实现 列表过滤 {{p.id}}:{{p.name}}:{{p.sex}} computed实现 列表过滤 {{p.id}}:{{p.name}}:{{p.sex}} 列表排序watch实现 列表排序 年龄升序 年龄降序 原顺序 {{p.id}}:{{p.name}}:{{p.sex}}:{{p.age}} computed实现 列表排序 年龄升序 年龄降序 原顺序 {{p.id}}:{{p.name}}:{{p.sex}}:{{p.age}}
Vue初识Vue想让Vue工作，就必须创建一个Vue实例，且要传入一个配置对象；root容器里的代码依然符合html规范，只不过混入了一些特殊的Vue语法；root容器里的代码被称为【Vue模板】；Vue实例和容器是一一对应的；真实开发中只有一个Vue实例，并且会配合着组件一起使用；{{xxx}}中的xxx要写js表达式，且xxx可以自动读取到data中的所有属性；一旦data中的数据发生改变，那么页面中用到该数据的地方也会自动更新； 初识Vue.html Hello，{{ language }} 模板语法插值语法：功能：用于解析标签体内容。写法：{{xxx}}，xxx是js表达式，且可以直接读取到data中的所有属性。指令语法：功能：用于解析标签（包括：标签属性、标签体内容、绑定事件.....）。举例：v-bind:href="xxx" 或 简写为 :href="xxx"，xxx同样要写js表达式，且可以直接读取到data中的所有属性。 模板语法 Hello，{{ language }}, I am {{ name.toUpperCase() }} this is my blog 数据绑定单向绑定(v-bind)：数据只能从data流向页面。双向绑定(v-model)：数据不仅能从data流向页面，还可以从页面流向data。双向绑定一般都应用在表单类元素上（如：input、select等），v-model:value 可以简写为 v-model，因为v-model默认收集的就是value值。 数据绑定 Hello，{{ language }}, I am {{ name.toUpperCase() }} this is my blog el与datael的2种写法new Vue时候配置el属性。 先创建Vue实例，随后再通过vm.$mount('#root')指定el的值。 data的2种写法对象式 函数式 MVVM模型MVVM模型M：模型(Model) ：data中的数据V：视图(View) ：模板代码VM：视图模型(ViewModel)：Vue实例观察发现：data中所有的属性，最后都出现在了vm身上。vm身上所有的属性 及 Vue原型上所有属性，在Vue模板中都可以直接使用。数据代理Object.defineproperty 数据代理通过一个对象代理对另一个对象中属性的操作（读/写） Vue中的数据代理Vue中的数据代理：通过vm对象来代理data对象中属性的操作（读/写）Vue中数据代理的好处：更加方便的操作data中的数据基本原理：通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性，都指定一个getter/setter。在getter/setter内部去操作（读/写）data中对应的属性。事件事件的基本使用：使用v-on:xxx 或 @xxx 绑定事件，其中xxx是事件名；事件的回调需要配置在methods对象中，最终会在vm上；methods中配置的函数，不要用箭头函数！否则this就不是vm了；methods中配置的函数，都是被Vue所管理的函数，this的指向是vm 或 组件实例对象；@click="demo" 和 @click="demo($event)" 效果一致，但后者可以传参； 事件处理 {{ "button1".toUpperCase() }} {{ "button2".toUpperCase() }} Vue中的事件修饰符：prevent：阻止默认事件（常用）stop：阻止事件冒泡（常用）once：事件只触发一次（常用）capture：使用事件的捕获模式self：只有event.target是当前操作的元素时才触发事件passive：事件的默认行为立即执行，无需等待事件回调执行完毕 事件修饰符 点我去Ronie的blog 这个按钮只能点一次 键盘事件Vue中常用的按键别名：回车 => enter删除 => delete (捕获“删除”和“退格”键)退出 => esc空格 => space换行 => tab (特殊，必须配合keydown去使用)上 => up下 => down左 => left右 => rightVue未提供别名的按键，可以使用按键原始的key值去绑定，但注意要转为kebab-case（短横线命名）系统修饰键（用法特殊）：ctrl、alt、shift、meta配合keyup使用：按下修饰键的同时，再按下其他键，随后释放其他键，事件才被触发。配合keydown使用：正常触发事件。也可以使用keyCode去指定具体的按键（不推荐）Vue.config.keyCodes.自定义键名 = 键码，可以去定制按键别名 键盘事件 欢迎来到{{name}}的Blog
数据显示视图数据显示视图是将后台的数据展示在网页上，数据主要来自模型，一共定义了四个视图类。RedirectView：用于实现HTTP重定向，默认只定义了GET请求的处理方法。TemplateView：视图类的基础视图，可将数据传递给HTML模板，默认只定义了GET请求的处理方法。ListView：在TemplateView的基础上将数据以列表显示，通常将某个数据表的数据以列表表示。DetailView：在在TemplateView的基础上将数据详细展示，通常获取数据表的单条数据。1.重定向视图RedirectViewRedirectView用于实现HTTP重定向功能，即网页跳转功能。在Django的源码内可以看到RedirectView的定义过程。从源码中可以看到RedirectView类，定义了四个属性和八个类方法。class RedirectView(View): """Provide a redirect on any GET request.""" permanent = False url = None pattern_name = None query_string = False def get_redirect_url(self, *args, **kwargs): """ Return the URL redirect to. Keyword arguments from the URL pattern match generating the redirect request are provided as kwargs to this method. """ if self.url: url = self.url % kwargs elif self.pattern_name: url = reverse(self.pattern_name, args=args, kwargs=kwargs) else: return None args = self.request.META.get("QUERY_STRING", "") if args and self.query_string: url = "%s?%s" % (url, args) return url def get(self, request, *args, **kwargs): url = self.get_redirect_url(*args, **kwargs) if url: if self.permanent: return HttpResponsePermanentRedirect(url) else: return HttpResponseRedirect(url) else: logger.warning( "Gone: %s", request.path, extra={"status_code": 410, "request": request} ) return HttpResponseGone() def head(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def options(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def patch(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) 其中permanent：根据属性值的真假来选择重定向的方式，若为True，则HTTP状态码为301，False则为302。url：代表重定向的路径。pattern_name：代表重定向的路由命名，若已经设置了url，则不用设置该参数。query_string：是否将当前路由地址的请求参传递到重定向的路由地址。get_redirect_url()：根据属性pattern_name所指向的路由命名来生成相应的路由地址。get()：触发HTTP的GET请求所执行的响应处理。其余类方法：是HTTP的不同请求方式，都由get()方法完成响应处理。# app的urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('turnTo/', views.turmTO.as_view(), name='turnTo'), ]# app的views.py from django.shortcuts import render from django.http import HttpResponse # Create your views here. from django.views.generic import RedirectView def index(request): return HttpResponse('hello world') class turmTO(RedirectView): permanent = False url = None pattern_name = 'index:index' query_string = False def get_redirect_url(self, *args, **kwargs): url = super().get_redirect_url(*args, **kwargs) print(url) return url# index.html模板 Redirect View turn 在app中定义了视图类turnTo，它继承父类RedirectView，对父类的属性和类方法进行重写，通过这样的方式可以扩展RedirectView的功能，从而满足开发需求。在定义路由时，使用视图类处理HTTP请求，则需要对视图类使用.as_view()方法（对视图类进行实例化处理），在开发时若需要对其他的HTTP请求进行处理，那么只需要重新定义相应的类方法即可。运行Django项目以上代码，可见September 16, 2022 - 22:54:47 Django version 4.1.1, using settings 'djangoProject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. [16/Sep/2022 22:54:48] "GET / HTTP/1.1" 200 11 redirect to / [16/Sep/2022 22:54:51] "GET /turnTo/ HTTP/1.1" 302 0 [16/Sep/2022 22:54:51] "GET / HTTP/1.1" 200 112.基础视图TemplateView视图类是所有视图类中的最基础的应用视图类，开发者可以直接调用应用视图类。它继承于多个父类，TemplateResponseMixin，ContextMixin和View，以下是TemplateView的源码class TemplateView(TemplateResponseMixin, ContextMixin, View): """ Render a template. Pass keyword arguments from the URLconf to the context. """ def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) return self.render_to_response(context)从代码中可以看出，它只定义了类方法 get()，该方法调用get_context_data()，render_to_response()方法从而完成HTTP请求的响应过程，get()方法中所调用的方法来自TemplateResponseMixin，ContextMixin。ContextMixin类中的get_context_data()方法用于获取模板上下文内容，模板上下文是将视图里的数据传递到模板文件，再由模板引擎转换为HTML网页数据。TemplateResponseMixin类中的render_to_response()方法用于实现响应处理，由响应类TemplateResponse处理。下面是TemplateResponseMixin类的定义。class TemplateResponseMixin: """A mixin that can be used to render a template.""" template_name = None template_engine = None response_class = TemplateResponse content_type = None def render_to_response(self, context, **response_kwargs): """ Return a response, using the `response_class` for this view, with a template rendered with the given context. Pass response_kwargs to the constructor of the response class. """ response_kwargs.setdefault("content_type", self.content_type) return self.response_class( request=self.request, template=self.get_template_names(), context=context, using=self.template_engine, **response_kwargs, ) def get_template_names(self): """ Return a list of template names to be used for the request. Must return a list. May not be called if render_to_response() is overridden. """ if self.template_name is None: raise ImproperlyConfigured( "TemplateResponseMixin requires either a definition of " "'template_name' or an implementation of 'get_template_names()'" ) else: return [self.template_name] template_name = None：设置模板文件的文件名template_engine = None：设置模板文件的模板引擎response_class = TemplateResponse：设置HTTP请求的响应类，默认为TemplateResponse类content_type = None：设置响应内容的数据格式render_to_response()：实现响应处理get_template_names()：获取属性template_name的值# app的urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index.as_view(), name='index'), ] # app 的views.py from django.shortcuts import render from django.http import HttpResponse # Create your views here. from django.views.generic import RedirectView, TemplateView class index(TemplateView): template_name = 'index.html' template_engine = None content_type = None extra_context = {'title': 'this is get'} def get_context_data(self, **kwargs): context = super(index, self).get_context_data(**kwargs) context['name'] = 'ronie' return context def post(self, request, *args, **kwargs): self.extra_context['title'] = 'this is post' print('set post') return self.render_to_response(self.get_context_data(**kwargs)) !! index.html Redirect View {{ title }} {{ name }} {% csrf_token %} 上述代码将网站首页的index视图函数改为index视图类，自定义视图类index继承自TemplateView类，重设了四个属性，重写了两个类方法。template_name：设置模板文件的index.htmltemplate_engine：设置模板文件的模板引擎content_type：设置响应内容的数据格式，none即代表数据为默认的text/htmlget_context_data()：继承并重写视图类TemplateView的类方法，在变量context里自定义namepost()：自定义post()请求的处理方法，当触发post请求时，重设属性值，并调用get_context_data()将属性extra_context写入，动态的改变模板的内容。当使用get访问时当使用点击post，使用post访问时bash信息September 17, 2022 - 19:39:26 Django version 4.1.1, using settings 'djangoProject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. [17/Sep/2022 19:39:27] "GET / HTTP/1.1" 200 372 set post [17/Sep/2022 19:40:16] "POST / HTTP/1.1" 200 3733.列表视图ListView视图是连接模板和路由的中心枢纽，同时视图还可以连接模型。模型指Django通过一定的规则来映射数据库，从而方便Django与数据库的交互。因为Django可以通过一定的规则来映射数据库，因此Django提供了视图类ListView，该视图类将数据表的数据以列表的形式显示，常用于数据库的查询。以下通过源码分析ListView的定义过程：class MultipleObjectMixin(ContextMixin): """A mixin for views manipulating multiple objects.""" allow_empty = True queryset = None model = None paginate_by = None paginate_orphans = 0 context_object_name = None paginator_class = Paginator page_kwarg = "page" ordering = None def get_queryset(self): """ Return the list of items for this view. The return value must be an iterable and may be an instance of `QuerySet` in which case `QuerySet` specific behavior will be enabled. """ def get_ordering(self): """Return the field or fields to use for ordering the queryset.""" def paginate_queryset(self, queryset, page_size): """Paginate the queryset, if needed.""" def get_paginate_by(self, queryset): """ Get the number of items to paginate by, or ``None`` for no pagination. """ def get_paginator( self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs ): """Return an instance of the paginator for this view.""" def get_paginate_orphans(self): """ Return the maximum number of orphans extend the last page by when paginating. """ def get_allow_empty(self): """ Return ``True`` if the view should display empty lists and ``False`` if a 404 should be raised instead. """ def get_context_object_name(self, object_list): """Get the name of the item to be used in the context.""" def get_context_data(self, *, object_list=None, **kwargs): """Get the context for this view.""" class BaseListView(MultipleObjectMixin, View): """A base view for displaying a list of objects.""" def get(self, request, *args, **kwargs): class MultipleObjectTemplateResponseMixin(TemplateResponseMixin): """Mixin for responding with a template and list of objects.""" template_name_suffix = "_list" def get_template_names(self): """ Return a list of template names to be used for the request. Must return a list. May not be called if render_to_response is overridden. """ class ListView(MultipleObjectTemplateResponseMixin, BaseListView): """ Render some list of objects, set by `self.model` or `self.queryset`. `self.queryset` can actually be any iterable of items, not just a queryset. """根据以上的继承关系可知，ListView的底层类是由TemplateResponseMixin，ContextMixin和View组成的，在这些底层类的基础上加入了模型的操作方法。通过分析得知，ListView类具有TemplateView类的全部属性和方法，此外i还新增了属性和方法。allow_empty = True：在模型查询数据不存在指导情况下是否显示页面，默认为True，若为false且数据不存在，则引发404异常。queryset = None：代表模型的查询对象，这是对模型对象进行查询操作所生成的查询对象。model = None：代表模型，一个模型代表一个数据表。paginate_by = None：代表每一页显示的数据量。paginate_orphans = 0：代表最后一页可以包含的溢出的数据量，防止最后一页数据量过少。context_object_name = None：设置模板上下文，即为模板变量命名。paginator_class = Paginator：设置分页的功能类，默认为内置分页Paginator。page_kwarg = "page"：设置分页参数名称，默认为page。ordering = None：对属性queryset查询结果进行排序。get_context_data(self, , object_list=None, *kwargs):获取模板上下文（模板变量的内容）。get_context_object_name(self, object_list):设置模板上下文的名称，若未设置，则上下文名称由模型名称+‘_list’表示。get_allow_empty(self):获取属性allow_empty的属性值。get_paginate_orphans(self):获取最后一页可以包含的溢出的数据量。get_paginator()：返回当前页数所对应的数据信息。get_paginate_by(self, queryset):获取每一页所显示的数据量。paginate_queryset(self, queryset, page_size):根据queryset的数据来进行分页处理。get_ordering(self):获取属性ordering的值get_queryset(self):获取queryset的值。get(self, request, args, *kwargs):定义HTTP的GET请求处理方式。get_template_names(self):获取属性template_name的值# app的urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index.as_view(), name='index'), ]# app的views.py from django.shortcuts import render from django.http import HttpResponse # Create your views here. from django.views.generic import RedirectView, TemplateView, ListView from .models import Person class index(ListView): template_name = 'index.html' queryset = Person.objects.all() extra_context = {'title': 'Person Info'} paginate_by = 2 context_object_name = 'Person' # app的models.py 记得执行makemigrations migrate，并向数据库中条件数据 from django.db import models # Create your models here. class Person(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) age = models.IntegerField() !index.html Redirect View {{ title }} name age {% for data in Person %} {{ data.name }} {{ data.age }} {% endfor %} {% if page_obj.has_previous %} previous page {% endif %} {% if page_obj.has_next %} next page {% endif %} 当前{{ page_obj.number }}页 共{{ page_obj.paginator.num_pages }}页 4.详细视图DetailView
FBV视图视图（view）是django MTV架构中的V部分，主要负责用户请求和生成相应的相应内容。我们用视图函数（定义def函数）处理处理HTTP请求，这种方式称为FBV。设置响应方式1. 返回响应内容：视图函数通过return方式返回响应内容，然后生成相应的网页内容呈现在浏览器上。若要设置不同的响应方式，则应使用django内置的响应类，内置的部分响应类如下： 响应类型 说明 HttpResponse(‘hello‘) 状态码200，请求被服务器成功接收 HttpResponseRedirect(‘/‘) 状态码302，重定向至首页 HttpResponsePermanentRedirect('/') 状态码301，永久重定向至首页/td> HttpResponseBadRequest('400') 状态码400，访问页面不存在或请求错误 HttpResponseNotFound('404') 状态码404，网页不存在或网页失效 HttpResponseForbidden('403') 状态码403，没有访问权限 HttpReseponseNotAllowed('405') 状态码405，不允许使用此请求方式 HttpReseponseServerError('500') 状态码500，服务器错误 不同的响应方式代表不同的HTTP状态码，作用是web服务器告诉浏览器当前网页的请求状态，例：# urls.py文件 from django.urls import path, re_path from . import views urlpatterns = [ path('', views.index), ]#views.py from django.shortcuts import render from django.http import HttpResponse import os # Create your views here. def index(request): return HttpResponse('hello world', status=200) # 返回200状态码，表示请求已被成功的接收并处理。render函数：从HttpResponse中可知，若要生成网页内容，就要将网页内容以字符串形式表示，这增加了代码量，同时也没有体现模板的作用，因此，django定义了render函数。def render(request, template_name, context=None, content_type=None, status=None, using=None):request：浏览器向服务器发送的请求对象，包含用户信息，请求方式等。template_name：设置模板文件名，用于生成网页内容。context：对模板变量进行赋值，以字典格式表示，默认为空字典。content_type：响应内容的数据格式，一般使用默认值。status：状态码，默认200.using：设置模板引擎，解析模板文件。# views.py from django.shortcuts import render from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse import os # Create your views here. def index(request): text = {'title': 'django'} # 传入模板文件index.html, return render(request, 'index.html', text) index {{ title }} 视图函数中定义变量text作为render的参数context，模板index.html里通过模板变量{{title}}获取变量text的数据，模板变量的命名必须与字典中的key名称相同。若传递的变量过多，则可以使用python的内置语法locals()取代参数context。2. 设置重定向：重定向的状态码为301与302，301重定向是永久重定向，302重定向是临时重定向，区别在于搜索引擎的抓取。django中定义了HttpResponseRedirect与HttpResponsePermanentRedirect类，这两个类继承于HttpResponseRedirectBase类，HttpResponseRedirectBase类继承于HttpResponse类。HttpResponseRedirect与HttpResponsePermanentRedirect类只需传入路由地址即可，但不支持路由命名传入。为解决路由命名传入，django定义了redirect函数(官方的注释已经很清楚了，不解释了)：# 官方定义 def redirect(to, *args, permanent=False, **kwargs): """ Return an HttpResponseRedirect to the appropriate URL for the arguments passed. The arguments could be: * A model: the model's `get_absolute_url()` function will be called. * A view name, possibly with arguments: `urls.reverse()` will be used to reverse-resolve the name. * A URL, which will be used as-is for the redirect location. Issues a temporary redirect by default; pass permanent=True to issue a permanent redirect. """ redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect return redirect_class(resolve_url(to, *args, **kwargs))3. 异常响应：异常响应是指状态码为404与500的响应状态。同一个网站的异常响应的所返回的页面都是相同的，因此应当在django中配置全局异常响应。django全局异常响应应在项目名下的urls.py文件中配置。# djangoProject/urls.py from django.contrib import admin from django.urls import path, re_path, include from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('index/', include(('index.urls', 'index'), namespace='index')), ] # 全局404页面配置 handler404 = 'index.views.page_not_found' # 全局500页面配置 handler500 = 'index.views.page_error'# index/urls.py from django.shortcuts import render # Create your views here. def page_not_found(request, exception): return render(request, '404.html', status=404) def page_error(request): return render(request, '500.html', status=500) 若要访问404和500页面则需要关闭django的Debug模式(DEBUG = False)，并更改ALLOWED_HOSTS = [‘*’]，否则你将看到django开发模式下的404页面或500页面。4. 文件下载功能：django提供三种方式实现文件下载功能，它们分别是HttpResponse，StreamingHttpResponse，FileResponse。HttpResponse：所有响应过程的核心类，底层功能类是HttpResponseBase。class HttpResponse(HttpResponseBase): """ An HTTP response class with a string as content. This content that can be read, appended to, or replaced. """StreamingHttpResponse：在HttpResponse类的基础上继承和重写，适用于大规模的数据响应和文件传输响应。class StreamingHttpResponse(HttpResponseBase): """ A streaming HTTP response class with an iterator as content. This should only be iterated once, when the response is streamed to the client. However, it can be appended to or replaced with a new iterator that wraps the original content (or yields entirely new content). """在StreamingHttpResponse类的基础上继承和重写，只适用于文件的传输响应。class FileResponse(StreamingHttpResponse): """ A streaming HTTP response class optimized for files. """HttpResponse，StreamingHttpResponse，FileResponse的差异：HttpResponse的工作原理是将文件读取并全部载入内存；如果下载的文件过大，就会占用过多的内存。StreamingHttpResponse，FileResponse都是将文件分批写入磁盘。StreamingHttpResponse适用范围更广，FileResponse适用于文件输出。使用方式：# djangoProject/urls.py from django.contrib import admin from django.urls import path, re_path, include from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('index/', include(('index.urls', 'index'), namespace='index')), ]# index/urls.py from django.urls import path, re_path from . import views urlpatterns = [ path('download/file1', views.download1, name='download1'), path('download/file2', views.download2, name='download2'), path('download/file3', views.download3, name='download3'), ]# index/views.py from django.shortcuts import render from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse import os # Create your views here. def download1(request): file_path = 'C:\\Users\\ren_r\\Desktop\\1.jpg' try: r = HttpResponse(open(file_path, 'rb')) r['content_type'] = 'application/octet-stream' r['Content-Disposition'] = 'attachment;filename=cat1.jpg' return r except Exception: raise Http404('Download error') def download2(request): file_path = 'C:\\Users\\ren_r\\Desktop\\2.jpg' try: r = StreamingHttpResponse(open(file_path, 'rb')) r['content_type'] = 'application/octet-stream' r['Content-Disposition'] = 'attachment;filename=cat2.jpg' return r except Exception: raise Http404('Download error') def download3(request): file_path = 'C:\\Users\\ren_r\\Desktop\\3.jpg' try: r = FileResponse(open(file_path, 'rb'), as_attachment=True, filename='nature.jpg') return r except Exception: raise Http404('Download error') index 1.jpg 2.jpg 3.jpg HTTP请求对象：1. HTTP请求对象：Django在接收到http请求之后，会根据http请求携带的参数以及报文信息创建一个WSGIRequest对象，并且作为视图函数第一个参数传给视图函数。也就是我们经常看到的request参数。在这个对象上我们可以找到客户端上传上来的所有信息。这个对象的完整路径是django.core.handlers.wsgi.WSGIRequest。WSGIRequest对象常用属性：path：请求服务器的完整“路径”，但不包含域名和参数。method：代表当前请求的http方法。比如是GET还是POST。GET：一个django.http.request.QueryDict对象。操作起来类似于字典。这个属性中包含了所有以?xxx=xxx的方式上传上来的参数。POST：也是一个django.http.request.QueryDict对象。这个属性中包含了所有以POST方式上传上来的参数。FILES：也是一个django.http.request.QueryDict对象。这个属性中包含了所有上传的文件。COOKIES：一个标准的Python字典，包含所有的cookie，键值对都是字符串类型。session：一个类似于字典的对象。用来操作服务器的session。META：存储的客户端发送上来的所有header信息。WSGIRequest对象常用方法：is_secure()：是否是采用https协议。is_ajax()：是否采用ajax发送的请求。原理就是判断请求头中是否存在X-Requested-With:XMLHttpRequest。get_host()：服务器的域名。如果在访问的时候还有端口号，那么会加上端口号。比如www.baidu.com:9000。get_full_path()：返回完整的path。如果有查询字符串，还会加上查询字符串。比如/music/bands/?print=True。get_raw_uri()：获取请求的原始的完整的url。2. 文件上传功能：# djangoProject/urls.py from django.contrib import admin from django.urls import path, re_path, include from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('index/', include(('index.urls', 'index'), namespace='index')), ]# index/views.py from django.shortcuts import render from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse import os # Create your views here. def upload(request): # 判断请求方法 if request.method == 'POST': # myFile对象包含了文件的基本信息，如:myFILE.name，myFILE.size，myFILE.content_type等。 myFile = request.FILES.get('myFile', None) if not myFile: return HttpResponse('upload failed') # 二进制写操作 f = open(os.path.join("e://", myFile.name), 'wb+') # 分块写文件，若使用myFile.read(),则会读取全部上传的数据，适用于小文件上传。myFile.chunks()分块读，用for语句分块写入文件。myFile.multiple_chunks()判断文件大小，文件大小小于>2.5MB返回True,否则返回False。用此方法可判断算法使用read()方法或chunks()方法。 for chunk in myFile.chunks(): f.write(chunk) f.close() return HttpResponse('upload over') else: return render(request, 'index.html') # index/urls.py from django.urls import path, re_path from . import views urlpatterns = [ path('upload/', views.upload, name='upload'), ] index
路由路由称为URL（统一资源定位符），是表示可以从互联网上得到的资源位置和访问方法的一种简洁的表示，是互联网上标准资源的地址。互联网上的每一个文件都有唯一的一个路由，用于指出网站文件的路径位置。1. django路由定义：在app文件夹内，添加urls.py文件，开发者应将所有属于该app的路由都写入该文件，因为这样更易于管理和区分每个路由地址。 Django Project中的urls.py是将每个app的urls.py统一管理。工作原理： 1.运行django项目时，django首先到DjangoProject文件夹下的urls.py中找到每个app所定义的路由，生成完整的路由列表。 2.用户在浏览器上访问某个路由地址时，django收到用户的请求信息。 3.django从请求信息中获取路由地址，并在路由表中匹配相应的路由信息，再执行由路由函数所指向的视图函数或视图类，从而完成整个请求响应过程。Django Project中的urls.py的代码如下：from django.contrib import admin from django.urls import path, re_path, include from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('index/', include('index.urls')), # app应用下的urls re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media') # 媒体文件 ]可以看到，首页地址将路由分发给index的urls.py进行处理，所以应当对index中的urls.py编写路由信息。 from django.urls import path from . import views urlpatterns = [ path('', views.index), ]views中的代码 from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse('hello world')路由文件urls.py的路由定义的规则是相对固定的，路由列表由urlpatterns表示，每个列表元素代表一条路由。路由是由django的path函数定义的，函数的第一个参数是路由地址，第二个参数是路由对应的视图处理函数。2. 路由变量的设置（建议在自己电脑上测试。）：Django在定义路由时，可以对路由设置变量值。路由的变量类型有字符类型，整形，slug，uuid字符类型：匹配任何非空字符串，不包含斜杠（默认使用）。整型：匹配自然数。slug：可理解为注释等概念，一般为路由的解释性字符。可匹配任何ASCII码字符以及连接符和下划线。uuid：匹配一个uuid格式的对象，所有字母必须小写。# index.urls中的代码 from django.urls import path from . import views urlpatterns = [ path('', views.index), path('<year>/<int:month>/<slug:day>', views.index2) # <year>数据类型为string,与<str:year>相同 # <int:month>,数据类型为int，变量名为month # <slug:day>,变量名为day，数据类型为slug ]# view.index2中的代码 def index2(request, year, month, day): return HttpResponse('hello django ' + str(year) + "-" + str(month) + "-" + str(day))django支持在路由地址之外设置变量（路由的可选变量），此变量是path函数中的第三个参数。参数只能以字典的形式出现。设置的参数只能在视图函数中读取和使用。字典的一个键值对代表一个参数，键代表参数名，值代表参数值。from django.urls import path from . import views urlpatterns = [ path('', views.index), # 添加了path变量的第三个参数 path('data/', views.index3, {'data': '2020/11/02'}), path('<year>/<int:month>/<slug:day>', views.index2) ]from django.shortcuts import render from django.http import HttpResponse # Create your views here. # 字典中的data键值对被使用 def index3(request, data): return HttpResponse('hello django ' + data)正则表达式路由的定义，正则表达式路由是由re_path函数定义的from django.urls import path, re_path from . import views urlpatterns = [ # 正则表达式匹配 re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index4), ] # ?P是固定格式，P必须大写 # <year>是变量名 # [0-9]{4}是正则表达式的匹配模式def index4(request, year, month): return HttpResponse('hello Django ' + " " + year + "/" + month)3. 命名空间与路由命名命名空间from django.contrib import admin from django.urls import path, re_path, include from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), # 可以看到include函数中的参数发生了变化 path('index/', include(('index.urls', 'index'), namespace='index')), path('user/', include(('user.urls', 'user'), namespace='user')), re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media'), ]路由函数设由参数args与namespace，参数args指向项目应用app下的urls.py文件；若要对设置namespace参数那么args参数必须是一个长度为2的元组，其中第0个元素是指项目应用的urls.py文件，第二个参数可自行命名一般与项目的应用名相同路由命名路由命名使用name参数，若路由中使用了include函数，那么没有必要再设置name参数。from django.urls import path, re_path from . import views urlpatterns = [ # 在path login中设置了name值 path('login/', views.login, name='login'), path('', views.index), path('data/', views.index3, {'data': '2020/11/02'}, name='data'), path('<year>/<int:month>/<slug:day>', views.index2, name='date'), re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index4), ]4. 路由的使用方式在模板中使用路由# 路由文件 from django.urls import path, re_path from . import views urlpatterns = [ path('', views.index), path('<year>/<month>/<day>', views.index2, name='date'),# 命名路由名字为date ]# 视图文件 from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return render(request, 'index.html') def index2(request, year, month, day): return HttpResponse('hello django ' + str(year) + "-" + str(month) + "-" + str(day)) index hello templates link link2 若路由地址存在变量，则模板语法需要设置相应的参数值，参数之间空格隔开。若路由地址不存在变量，则不需设置参数值，设置路由名称即可。若地址存在变量，但参数数量与url参数不同，django报错。反向解析reverse与resolvereverse：通过路由命名或可调用视图对象来生成路由地址。def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):viewname：代表路由命名或可调用路由对象，一般以路由命名name来生成路由地址。urlconf：设置反向解析的URLconf模块。args：以列表方式传递路由地址变量，列表元素顺序和数量应与路由地址变量的顺序和数量相同。kwargs：以字典方式传递路由变量。current_app：提示当前正在执行的视图所在的项目应用，几乎无用。resolve：通过路由地址来获得路由对象信息。def resolve(path, urlconf=None):path：路由地址。urlconf：设置反向解析的URLconf模块。# 自己运行一遍# view代码 from django.shortcuts import render, reverse from django.http import HttpResponse from django.urls import resolve # Create your views here. def index(request): kwargs = {'name': 'ronie'} args = ['ronie'] print(reverse('guest:name', args=args)) # args与kwargs参数不能同时设置 print(reverse('guest:name', kwargs=kwargs)) return HttpResponse(reverse('guest:name', args=args)) def name(request, name_): args = ['ronie'] result = resolve(reverse('guest:name', args=args)) print('kwargs: ', result.kwargs) print('url_name: ', result.url_name) print('namespace: ', result.namespace) print('view_name: ', result.view_name) print('app_name: ', result.app_name) return HttpResponse(name_)# urls.py代码 from django.urls import path, re_path from . import views urlpatterns = [ path('', views.index, name='index'),# 主页 path('<name_>', views.name, name='name'), ]5. 路由重定向：重定向：建议百度。django网页重定向的方式有两种路由重定向：使用django视图类RedirectView实现，默认用HTTP的get请求。# urls.py文件 from django.urls import path, re_path from . import views from django.views.generic import RedirectView urlpatterns = [ path('', views.index, name='index'), path('<name_>', views.name, name='name'), # 在路由中重定向 path('turnTo/', RedirectView.as_view(url='/index'), name='turnTo'), ] 自定义视图重定向：自定义视图的响应状态设置重定向。# view文件 from django.shortcuts import render, reverse, redirect from django.http import HttpResponse from django.urls import resolve # Create your views here. def name(request, name_): args = ['ronie'] result = resolve(reverse('guest:name', args=args)) print('kwargs: ', result.kwargs) print('url_name: ', result.url_name) print('namespace: ', result.namespace) print('view_name: ', result.view_name) print('app_name: ', result.app_name) return HttpResponse(name_) # 通过重定向函数redirect重定向 def turnTo(request): return redirect(reverse('guest:name', args=['ronie'])) # redirect函数
1.Django 配置信息基本配置信息：BASE_DIR = Path(__file__).resolve().parent.parentdjango项目的工作目录。SECRET_KEY = ')o+504x)+hi#xh7ap01ouru@spqn5tj3od%9xlcd!0d9=0#bk('密匙配置，在创建项目的时候产生，一般无需修改。主要用于重要数据的加密处理。提高项目安全性，避免受到攻击者的恶意破坏。DEBUG = True调试模式，若在开发模式，则应该设置为True，若项目部署上线则应该改为False。在开发模式中Django会自动检测代码是否被修改，根据结果确认是否重启服务器。ALLOWED_HOSTS = []域名访问权限，设置可访问的域名，默认为空。当DEBUG = True时且ALLOWED_HOSTS为空列表时，项目只允许以localhost或127.0.0.1在浏览器访问，当DEBUG = False时，ALLOW_HOSTS 为必填项，负责项目无法启动，若想所有域名均可访问，设置ALLOWED_HOSTS = ['*']。INSTALLED_APPS = [ 'django.contrib.admin', # 后台管理系统 'django.contrib.auth', # 用户认证系统 'django.contrib.contenttypes', # 记录项目中所有的model元数据 'django.contrib.sessions', # session会话功能，用于标识当前访问网站的用户身份，记录用户信息。 'django.contrib.messages', # 消息提示功能 'django.contrib.staticfiles', # 查找静态资源路径 'index' # 自己添加的app ]资源文件配置：资源文件配置分为静态资源和媒体资源。静态资源的配置由配置属性STATIC_URL，STATICFILES_DIRS和STATIC_ROOT进行设置，媒体资源文件的配置方式由配置属性MEDIA_URL和MEDIA_ROOT决定。资源路由（STATIC_URL）：# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/'静态资源指网站中不会改变的文件。例如css，JavaScript，图片等文件。若资源路由STATIC_URL的值为/static/，则浏览器访问静态资源的网站必须为static，否则无法访问，且在调试模式下只能识别app目录下的static文件夹。资源集合（STATICFILES_DIRS）：STATICFILES_DIRS = [os.path.join(BASE_DIR, 'MYSTATIC1'), os.path.join(BASE_DIR, 'MYSTATIC2'),]资源部署（STATIC_ROOT）:STATIC_ROOT = os.path.join(BASE_DIR, 'allStatic')STATIC_ROOT的作用是在服务器部署项目，实现服务器和项目之间的映射。STATIC_ROOT收集整个项目的静态资源并放在一个文件夹中，然后由该文件夹与服务器之间构建映射关系。当在调试模式时，Django会自动提供静态文件的代理服务，当进入生产环境时，需要设置STATIC_ROOT。媒体资源（MEDIA）:# 媒体路由地址信息 MEDIA_URL = '/media/' # media文件夹的完整路径信息 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')设置完成后还需要让Django找到配置信息：打开DjangoProject中的urls.py，为媒体文件夹添加路由地址。from django.contrib import admin from django.urls import path, re_path from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media') ]模板配置：模板是一种较特殊的HTML文档。文档中嵌入了一些django能够识别的变量和指令，然后由django的模板引擎解析这些变量和指令，生成完整的网页返回给用户浏览。# django默认的模板配置信息 TEMPLATES = [ { # BACKEND: 定义模板引擎，内置模板引擎有DjangoTemplates与jinja2.Jania2 'BACKEND': 'django.template.backends.django.DjangoTemplates', # DIRS: 设置模板所在路径，默认为空 'DIRS': [BASE_DIR / 'templates'] # APP_DIRS: 是否在app里查找模板文件。 'APP_DIRS': True, # OPTIONS: 用于填充RequestContext的上下文，一般不改。 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]数据库配置：django提供四种数据库引擎：MySQL，Oracle，sqlite3，postgresql。项目创建时默认使用sqlite3。DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }若想使用MySQL数据库，则应当安装mysqlclient库，并将上述代码改为DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_db', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '3306', } } 若想使用多个数据库，则应当将代码改为DATABASES = { # 第一个数据库 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_db', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '3306', }, # 第二个数据库 'Database1': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', }, #第三个数据库 'Database2': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'django_db2', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '1521', } }中间件：中间件顾名思义，是介于request与response处理之间的一道处理过程，相对比较轻量级，并且在全局上改变django的输入与输出。# django默认的中间件，一般不需要更改，能满足大部分开发需求 MIDDLEWARE = [ # 内置的安全机制，保护用户与网站间的通信安全。 'django.middleware.security.SecurityMiddleware', # session会话功能 'django.contrib.sessions.middleware.SessionMiddleware', # 处理请求信息 'django.middleware.common.CommonMiddleware', # csrf防护功能 'django.middleware.csrf.CsrfViewMiddleware', # 开启内置的用户认证系统 'django.contrib.auth.middleware.AuthenticationMiddleware', # 开启内置的信息提示功能 'django.contrib.messages.middleware.MessageMiddleware', # 防止恶意程序单击劫持 'django.middleware.clickjacking.XFrameOptionsMiddleware',