django 记录一 基本配置、模板和单表查询

路由系统


urls.py配置

# url(正在表达式, 视图参数, 可选参数)

from django.conf.urls import url
from django.contrib import admin
from app_01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),   
]

# 无分名组
url(r'^index/(\d+)/(\d+)/',views.index)    # def index(request,n,m)  位置参数

# 有分名组
url(r'^index/(?P<year>\d+)/(?P<month>\d+)/',views.index)    # def index(request,year,month) 关键字参数,参数顺序不要求

# 视图函数参数默认值
url(r'^index/$',views.index),
url(r'^index/(?P<num>\d+)/,views.index)    # def index(request,num='1'):
# 分发路由include

# 项目的urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^$', views.base),    # 首页
    url(r'^app01/', include('app01.urls')),    # app01的分发路由
    url(r'^app02/', include('app02.urls')),    # app02的分发路由
    ]

# app01的urls.py    自己创建
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^$', views.app01base),
    url(r'^index/', views.index),
    ]

# app02的urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^$', views.app02base),
    url(r'^index/', views.index),
    ]

url别名反向解析

  • 将url添加别名,并且根据别名能够正确调取url地址
  • 灵活配置,无论前面怎么变,都能根据别名正确找到想要的地址
# urls.py

urlpatterns = [
    url(r'^home', views.home, name='home'),
    url(r'^index/(\d*)', views.index, name='index'),
]
# html

{% url 'home' %}
{% url 'index' num %}
# views.py

from django.urls import reverse

def home(request):
    # return redirect(reverse("index", args=("2018", )))
    return redirect(reverse('别名'))

url命名空间

  • 解决不同app相同的url别名冲突
  • app名字:命名空间:url别名(寻找顺序)
# urls.py
from django.conf.urls import url, include
 
urlpatterns = [
    url(r'^app01/', include('app01.urls', namespace='app01')),
    url(r'^app02/', include('app02.urls', namespace='app02')),
]

# app01.urls
from django.conf.urls import url
from app01 import views
 
urlpatterns = [
    url(r'index/', views.index, name='index')
]

# app02.urls
# app01.urls
from django.conf.urls import url
from app02 import views
 
urlpatterns = [
    url(r'index/', views.index, name='index')
]

# 模板
{% url 'app01:index' %}

# 视图
v = reverse('app01:index')

 

视图views


请求相关(request——HttpRequest对象)

request.method        # 判断请求方式
request.body          # 获取post请求提交过来的原始数据 byte类型
request.POST          # 获取post请求提交的数据
request.GET           # 获取get请求提交的数据
request.GET.urlencode()    # name=demo&age=18
request.META          # 请求头相关信息,一个大字典
request.path          # 路径 /crm/customer_show/
request.path_info     # 路径 /crm/customer_show/
request.is_ajax()     # 判断是否为ajax请求
request.get_full_path()    # /crm/customer_show/?page=5&abc=123&bcd=345
request.GET.copy()    # 将 request.GET对象改成可修改的

响应相关

from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from django.utils.safestring import mark_safe

HttpResponse    # 回复字符串时候使用
render          # 回复一个html页面时候使用
redirect        # 重定向
JsonResponse    # 将数据转换为json形式回复页面,如果是数组需要添加参数safe=False
mark_safe       # 如果返回的是html页面代码块,如ht="<a href=''></a>"这种内容,用mark_safe返回,相当于页面{{ ht|safe }}

 

FBV和CBV


# FBV (function based view)
def home(request):
    print('home!!!')
    return render(request,'home.html')
# CBV (class based view)

from django.views import View

class LoginView(View):
    # 通过请求方法找到自己写的视图类里面对应的方法
    def get(self,request):
        return render(request,'login2.html')
    
    def post(self,request):
        username = request.POST.get('uname')
        password = request.POST.get('pwd')
        print(username,password)
            return HttpResponse('登录成功!')
       
     
# urls.py
url(r'^login2/', views.LoginView.as_view()),

CBV中dispatch做中间件

具体dispatch作用可看我的另一篇文章:django 源码部分

class LoginView(View):
    def dispatch(self, request, *args, **kwargs):
        print("请求来了")
        ret = super().dispatch(request, *args, **kwargs)
        print("我走了")
        return ret


# 请求来了
# [15/Jul/2020 11:40:11] "GET /app02/login/ HTTP/1.1" 200 443
# 我走了

FBV加装饰器

def wrapper(f):
    def inner(*args, **kwargs):
        print("请求前做的事情")
        ret = f(*args, **kwargs)
        print("请求之后做的事情")
        return ret
    return inner


@wrapper
def login(request):
    print("login")
    return HttpResponse("200")

CBV加装饰器

from django.utils.decorators import method_decorator


def wrapper(f):
    def inner(*args, **kwargs):
        print("请求前做的事情")
        ret = f(*args, **kwargs)
        print("请求之后做的事情")
        return ret
    return inner

# @method_decorator(wrapper, name='get')      # 方法二
class LoginView(View):
    @method_decorator(wrapper)                # 方法三:给所有方法加装饰器
    def dispatch(self, request, *args, **kwargs):
        print("请求来了")
        ret = super().dispatch(request, *args, **kwargs)
        print("我走了")
        return ret

    def get(self, request):
        print("get方法")
        return render(request, "login.html")

    # @method_decorator(wrapper)      # 方法一
    def post(self, request):
        usr = request.POST.get("username")
        pwd = request.POST.get("password")
        print(f'{usr}--{pwd}')
        return HttpResponse("200")

 

模板


语法:
{{ 变量 }}
{% 逻辑 %}

 深度查询(.)

# 深度查询据点符(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:
# 字典查询(Dictionary lookup)
# 属性或方法查询(Attribute or method lookup)
# 数字索引查询(Numeric index lookup)


# views
def index(request):
    num = 10
    name = "路飞"
    name_list = ["路飞", "娜美", "索隆"]
    name_dict = {"name": "路飞", "hobby": "吃肉"}

    class Animal:
        def __init__(self):
            self.kind = "dog"

        def eat(self):
            return "肉"
    a = Animal()
    return render(request, "index.html", {"num": num, "name": name, "name_list": name_list, "name_dic": name_dict, "a": a})
    # return render(request, "index.html", locals())        # 将所有数据都封装到一个大字典中


# html 取值
<body>
<p>{{ num }}</p>            # 10        
<p>{{ name }}</p>           # 路飞
<p>{{ name_list }}————{{ name_list.1 }}</p>    # ['路飞', '娜美', '索隆']————娜美
<p>{{ name_dic }}————{{ name_dic.name }}</p>   # {'name': '路飞', 'hobby': '吃肉'}————路飞
<p>{{ a }}--{{ a.kind }}————{{ a.eat }}</p>    # <app01.views.index.<locals>.Animal object at 0x000001B158E8DBA8>--dog————肉
</body>

常用过滤器

{{ value|default:"nothing" }}    # 变量为空或false时给定默认值
{{ value|length }}               # 返回值的长度
{{ value|filesizeformat }}       # 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)
{{ value|slice:"1:5" }}          # 切片
{{ value|date:"Y-m-d H:i:s" }}   # 时间格式化
{{ value|truncatechars:9}}       # 如果字符串大于指定长度则以...省略结尾
{{ value|truncatewords:3}}       # 截断字符串,如:路飞 娜美 索隆 罗宾 返回:路飞 娜美 索隆...
{{ value|cut:' ' }}              # 移除value中所有的与给出的变量相同的字符串
{{ value|join:'+' }}             # 使用字符串连接,跟python的join一样
{{ value|safe }}                 # 表示字符安全,如果value为script如果不写safe会被当成字符串处理

for循环标签

# 普通循环
{% for i in 数据 %}
    {{ i }}
{% endfor %}

# 字典循环
{% for k,v in 字典.items %}
    {{ k }}——{{ v }}
{{ endfor }}

# empty
<ul>
    {% for foo in 数据 %}
        <li>{{ foo }}</li>
    {% empty %}
        <li>查询的内容啥也没有</li>
    {% endfor %}
</ul>

for循环其他方法

forloop.counter            # 当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0           # 当前循环的索引值(从0开始)
forloop.revcounter         # 当前循环的倒序索引值(从1开始)
forloop.revcounter0        # 当前循环的倒序索引值(从0开始)
forloop.first              # 当前循环是不是第一次循环(布尔值)
forloop.last               # 当前循环是不是最后一次循环(布尔值)
forloop.parentloop         # 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
forloop.parentloop.counter
# 数据源:name_list = ["路飞", "娜美", "索隆"]

{% for i in name_list %}
    {{ forloop.counter }}
    {{ i }}                    # 1 路飞 2 娜美 3 索隆
{% endfor %}       

{% for i in name_list %}
    {{ forloop.counter0 }}
    {{ i }}                    # 0 路飞 1 娜美 2 索隆
{% endfor %}      

{% for i in name_list %}
    {{ forloop.revcounter }}
    {{ i }}                    # 3 路飞 2 娜美 1 索隆   
{% endfor %} 
  
{% for i in name_list %}
    {{ forloop.revcounter0 }}
    {{ i }}                    # 2 路飞 1 娜美 0 索隆
{% endfor %}

{% for i in name_list %}
    {{ forloop.first }}
    {{ i }}                    # True 路飞 False 娜美 False 索隆
{% endfor %}

# 数据源:name_hobby = [["路飞", "吃饭", "睡觉"], ["布鲁克", "牛奶", "内裤"]]
<ul>
    {% for foo in name_hobby %}
        <li>
            {% for fo in foo %}
                {{ forloop.parentloop.counter }}
{#                {{ forloop.counter }}#}
                <a href="">{{ fo }}</a>        # 1 路飞 1 吃饭 1 睡觉
            {% endfor %}                       # 2 布鲁克 2 牛奶 2 内裤
        </li>
    {% endfor %}
</ul>

if标签

{% if num > 100 or num < 0 %}
    <p>无效</p>      <!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}          <!--也是在if标签结构里面的-->
    <p>凑活吧</p>
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。

with标签

# 给一个复杂的变量起别名
{% with total=business.employees.count %}
    {{ total }} <!--只能在with语句体内用-->
{% endwith %}

csrf_token

用于跨站请求伪造保护,post提交数据时候使用。
在<form>表单里面加上{% csrf_token %},会在提交数据时候加上一个input标签,里面存放一个随机的value字符串,django会校验这个value随机字符串,如果和django存放的一致,则通过验证。防止反爬虫和恶意攻击

装饰器
在视图函数上面加 @csrf_exempt 允许跨站请求   @csrf_protect 不允许跨站请求

 

模板继承


  • 当我们其他页面大体布局和一些内容和上面的html很相似时候,就可以创建一个母版(base.html)页面,其他页面继承模板,并且在自己相应需要修改的地方引入(extend)自己文件。
  • 在模板中创建多个钩子,最少得有css、js、页面的钩子
# base.html 母版文件
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %} My base html {% endblock title %}</title>
</head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
        {% endblock sidebar %}
    </div>

    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>
{% extends "base.html" %}

# 子版继承模板,并在相应钩子地方写自己的内容

{% block title %}
    xxx
{% endblock title %}

{% block sidebar %}
    yyy
{% endblock sidebar %}

{% block content %}
    zzz
{% endblock %}

 

组件


  • 类似模板,他是将常用的页面内容如导航条、页尾信息等组件保存到单独的文件中,文件任意位置导入即可
<!DOCTYPE html>
# nav.html 导航条
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
            background-color: red;
            height: 40px;
        }
    </style>
</head>
<body>

<div class="c1">
    <div>
        <a href="">xx</a>
        <a href="">dd</a>
    </div>
</div>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% include 'nav.html' %}
<h1>xxxxxxxxxx</h1>
</body>
</html>

 

自定义标签和过滤器


自定义过滤器

  • 在app应用的文件夹下创建templatetags文件夹,必须是这个名字
  • 在templatetags创建任意名字的py文件
  • 带参数的过滤器最多只能有两个参数
  • 可以放在if  for等语句后
# app01/templatetags/my_filter.py
from django import template

register = template.Library()   # register的名字是固定的,不可改变


@register.filter
def filter_ride(v1, v2):    # 带参数过滤器,参数最多只能有2个
    return v1*v2


@register.filter
def filter_add_str(v1):     # 不带参数的过滤器
    s = v1 + '添加点信息'
    return s


# html
{% load my_filter %}        # 加载过滤器文件
{{ name|filter_add_str }}   # 路飞 娜美 索隆 罗宾添加点信息
{{ num|filter_ride:5 }}     # 50

自定义标签

  • 在app应用的文件夹下创建templatetags文件夹,必须是这个名字
  • 在templatetags创建任意名字的py文件
  • 不能用在if  for等语句后
# app01/templatetags/my_tags.py
from django import template

register = template.Library()   # register的名字是固定的,不可改变


@register.simple_tag
def tag_ride(v1, v2, v3, v4):    # 可传多个参数
    n = v1*v2*v3*v4
    return n


# html
{% load my_tags %}

{% tag_ride num 5 6 7  %}

inclusion_tag

  • 多用于返回html代码片段
  • 也是在templatetags文件下创建
  • 创建一个html代码片段,py文件做逻辑插入数据等,其他页面在调用py
# result.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>片段</title>
</head>
<body>
<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>
</body>
</html>

# app01\templatetags\my_inclusion.py
from django import template

register = template.Library()


@register.inclusion_tag('result.html')  # 将result.html里面的内容用下面函数的返回值渲染,然后作为一个组件一样,加载到使用这个函数的html文件里面
def show_results(n):                    # 参数可以传多个进来
    n = 1 if n < 1 else int(n)
    data = ["第{}项".format(i) for i in range(1, n+1)]
    return {"data": data}               # 这里可以穿多个值,和render的感觉是一样的{'data1':data1,'data2':data2....}

# index.html 在需要的地方插入
{% load my_inclusion %}

{% show_results 10 %}

 

静态文件配置


  • 像css,js,img等不需要修改的文件,我们最好单独放一个静态文件夹中
  • 在setting中进行静态文件配置,否则django找不到
STATIC_URL = '/static/' #别名

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static_files'), # 第二个参数就是项目中你存放静态文件的文件夹名称
]
{% load static %}    # 声明在html最上面

<link rel="stylesheet" href="{% static 'bootstrap.css' %}">
<script src="{% static "jquery-3.3.1.min.js" %}"></script>
<img src="{% static "星空star.jpg" %}">

# 获取静态文件名称 get_static_prefix = /static/   as STATIC_PREFIX = 起个别名,后面方便引用 
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值