django

 参考:http://www.cnblogs.com/wupeiqi/articles/5237704.html

http://www.cnblogs.com/wupeiqi/articles/5341480.html

http://www.cnblogs.com/wupeiqi/articles/5246483.html

客户端访问服务器的时候,访问对应函数,函数会返回字符串到客户端
1、django请求生命周期:
  -》URL对应关系(匹配) -》 视图函数 -》返回用户字符串;
  -》URL对应关系(匹配) -》 视图函数 -》打开一个HTML文件,读取内容

安装

mysite
    mysite             #对整个程序进行配置
        -init
        -setting    #配置文件
        -url        #URL对应关系
        -wsgi        #遵循WSGI规范,uwsgi + nginx
    -manage.py        #管理Django程序:
                    -python manage.py
                    -python manage.py startapp xx 创建app
                    -python manage.py makemigrations
                    -python manage.py migrate

wsgi:遵循wsgi规则的是以下东西

  'cgi': CGIServer,
    'flup': FlupFCGIServer,
    'wsgiref': WSGIRefServer,
    'waitress': WaitressServer,
    'cherrypy': CherryPyServer,
    'paste': PasteServer,
    'fapws3': FapwsServer,
    'tornado': TornadoServer,
    'gae': AppEngineServer,
    'twisted': TwistedServer,
    'diesel': DieselServer,
    'meinheld': MeinheldServer,
    'gunicorn': GunicornServer,
    'eventlet': EventletServer,
    'gevent': GeventServer,
    'geventSocketIO':GeventSocketIOServer,
    'rocket': RocketServer,
    'bjoern' : BjoernServer,
    'auto': AutoServer,

pip3 install django

安装完毕后,python目录就会增加两个文件,然后将这个目录C:Python36Scripts增加到环境变量

django-admin.exe  startproject laoniu

运行命令提示符,D盘目录将会增加laoniu文件夹;

命令提示符,进入该目录,输入命令python manage.py runserver 127.0.0.1:8001

 pycharm启用django

选中对应项目,然后启动(修改访问端口也是这里硒鼓)

若是没有对应django server,需要编辑结构,选中左上角的+,增加上去

 

 创建app

chouti
  -chouti
    -配置
  -主站 app
  -后台管理 app


python manage.py startapp cmdb
python manage.py startapp openstack

python manage.py startapp makemigrations
python manage.py startapp xxxx

app:

  makemigrations:      修改数据库表结构的记录

  admin        Django为我们提供的后台管理

  apps          配置当前app

  models        ORM,写指定的类,通过命令可以创建数据库结构

  tests          单元测试

  views        业务代码

1.配置模板的路径

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR),"templates"],
        'APP_DIRS': True,
        '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',
            ],
        },
    },
]

2.配置静态目录

静态文件对应客户端请求,需要在settings配置文件最后加上


STATICFIES_DIRS = (
# 这里必须要有逗号
os.path.join(BASE_DIR,'static'),
)

settings文件注释 MIDDLEWARE 的'django.middleware.csrf.CsrfViewMiddleware',
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

4、编写程序

a.url.py
  /inde/ -> func

b. views.py(参数是必须的,包含了所有的客户端请求信息)
  def func(request):

    ...
    return HttpResponse('字符串')      return HttpResponse(bytes('字符串')),可以返回字符串以及字节
    return render(request,'index.html',{{''}})  渲染页面
    return ret('URL')            页面跳转

c. 模板语言
  return render(request,'index.html',{{'l1':[11,22,33]}})
  {%for item in..%}
    <h1>{{item}}</h1>
  {{endfor}}

  只要有for就有forloop

  forloop.counter      counter的意思是循环一次+1,初始值为0

  forloop.revcounter      counter的意思是循环一次-1,最后值为0

  forloop last


{{for}}

  {{if num = 1}}
    return true
  {{endif}}

{{endfor}}


request.Get:  获取数据
request.POAT:  提交数据
request.FILES  #获取文件信息
 
u = request.POST.get('user')     #get只能获取一个值  radio
v = request.POST.getlist('favor')  #getlist 获取多个值,列表;一般用于CheckBox,select-option多选组合等


 # django处理文件一般是用request.FILES,request.FILES.get是获取文件信息,默认返回是文件名称
        obj = request.FILES.get('file')
        print(obj,type(obj))

        import os
        file_path = os.path.join('upload',obj.name)
#上传文件
        f = open(file_path,mode='wb')
        # chunks 相当于一段段获取文件信息
        for i in obj.chunks():
            f.write(i)
        f.close()
#要上传文件,需要再form上面加上enctype="multipart/form-data"#}
<form action="/login/" method="post" enctype="multipart/form-data"> </form>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#要上传文件,需要再form上面加上enctype="multipart/form-data"#}
    <form action="/login/" method="post" enctype="multipart/form-data">
        <p>
            <input type="text"name="user" placeholder="用户名"/>
        </p>
         <p>
            <input type="password"name="pwd" placeholder="密码"/>
        </p>
        <p><input type="radio" name="gender" value="1" /><input type="radio" name="gender" value="2" /><input type="radio" name="gender" value="3" />
        </p>
        <p>
            篮球<input type="checkbox" name="favor" value="11" />
            足球<input type="checkbox" name="favor" value="22" />
            排球<input type="checkbox" name="favor" value="33" />
        </p>
        <p>
{#            多了multiple,可以多选,所以后端必须写收取多个值的getlist#}
            <select name="city" multiple>
                <option value="sh">上海</option>
                <option value="bj">北京</option>
                <option value="tj">天津</option>
            </select>
        </p>

        <p>
            <input type="file" value="上传文件" name="file" />
        </p>

        <input type="submit" value="提交" />
    </form>
</body>
</html>
login.html

获取字典信息:

user_dict.keys    #字典的key

user_dict.values    #字典的value

user_dict.items    #字典的key和value

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <ul>
      {% for k in user_dict.keys %}
            <li>{{ k }}</li>
      {% endfor %}
        <p></p>
      {% for v in user_dict.values %}
            <li>{{ v }}</li>
      {% endfor %}
        <p></p>
      {% for k,v in user_dict.items %}
            <li>{{ k }} - {{ v }}</li>
      {% endfor %}

  </ul>

</body>
</html>
index.html

类的操作:

  客户端发送信息到服务器,经过from django.views import View的View的dispatch,将方法转换为小写英文之后,进行反射到对应的方法

    def dispatch(self, request, *args, **kwargs):
        '''
        调用父类中的dispatch,进行重写,这样可以实现类似装饰器那样的功能
        '''
        print('before')
        result = super(Home,self).dispatch(request, *args, **kwargs)
        print('after')
        return result
from django.shortcuts import render
from django.shortcuts import HttpResponse

# Create your views here.

def index(request):
    return HttpResponse('Index')

from django.views import View
class Home(View):

    def dispatch(self, request, *args, **kwargs):
        '''
        调用父类中的dispatch,进行重写,这样可以实现类似装饰器那样的功能
        '''
        print('before')
        result = super(Home,self).dispatch(request, *args, **kwargs)
        print('after')
        return result

    def get(self,request):
        '''
        如果是get方法获取,则执行这个方法
        :param request:
        :return:
        '''
        print(request.method)
        return render(request,'home.html')
    def post(self,request):
        '''
        如果是post方法获取,则执行这个方法
        :param request:
        :return:
        '''
        print(request.method)
        return render(request,'home.html')
viess.py
"""day19 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from migrations import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),

    # 关联类的固定写法,关联类Home的as_view方法
    path('home/', views.Home.as_view()),
]
url.py

一、路由系统,URL

  

1、url(r'^index/', views.index),    
       url(r'^home/', views.Home.as_view()),
    2、url(r'^detail-(d+).html', views.detail),  
    3、url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail)(推荐使用这个,配合下图的代码使用)
  4、url('index/',views.index,name='indexx'),

  url.py
  url(r'^datail-(d+).html', views.datail),
  
  views.py
  def datail(request,nid):
  user_info = USER_DICT[nid]
  return render(request,'detail.html',{"user_info":user_info})

  index.html
   {% for k,v in user_dict.items %}
<li> <a target="_blank" href="/datail-{{ k }}.html">{{ v.username }}</a></li>
  {% endfor %}
  
  

  建议使用的方法:

  

  url.py:  url('index/',views.index,name='indexx'),
  
 <form action='{% url "indexx" %}' method="post">
        <p>
            <input type="text" name="user" placeholder="用户名" />
        </p>
          <p>
            <input type="text" name="email" placeholder="邮箱" />
        </p>
          <p>
            <input type="submit" value="提交" />
        </p>
    </form>
name:
  对URL路由关系进行命名,以后可以根据此名称生成自己想要的URL
  
url('index/',views.index,name='indexx')
url('index/(d+)/(d+)/',views.index,name='indexx')
url('index/(?P<pid>d+)/(?P<uid>d+)/',views.index,name='indexx')


模板语言:
  {% url "indexx" %}
  {% url "indexx 3 4" %}

注意:request.path_info    #当前的URL

 当请求过来的时候,优先匹配project同名目录下的urls.py,然后再分发给其他目录下的urls.py


默认值



  

二、视图

三、模板

四、ORM操作

   

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'back_logs',
        'USER':'root',
        'PASSWORD': 'Choice123',
        'HOST':'localhost',
        'PORT':'3306'
    }
}
# 如果想用mysql数据库
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.mysql',
#         'NAME': 'dbname',
#         'USER':'root',
#         'PASSWORD': 'XXX',
#         'HOST':'',
#         'PORT':','
#     }
# }

 修改之后,需要再init.py文件里面写入代码

import pymysql
pymysql.install_as_MySQLdb()



  select * from tb where id > 1

  #对应关系

  models.tb.objects.filter(id__gt=1)    #id大于1

  models.tb.objects.filter(idt=1)      #id等于1

  models.tb.objects.filter(id__lt=1)    #id小于1

  创建类

    1、根据类自动创建数据库表

      #app下的models.py 先写类

      

# 必须要继承models.Model
# 表名叫:app01_userinfo
class UserInfo(models.Model):


    # id列,自增,主键(django自动创建)
    # 用户名列,字符串类型,指定长度
    username = models.CharField(max_length=32)
    # 密码列,字符串类型,指定长度
    password = models.CharField(max_length=64)

      注册app:

      settings.py文件下,找到INSTALLED_APPS,增加app目录名称(# django会根据这里找app01目录下的migrations)
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # django会根据这里找app01目录下的migrations
    'app01',
]

     然后执行命令: 

              python manage.py makemigrations

           python manage.py migrate

 model操作

   参考:https://www.cnblogs.com/wupeiqi/articles/6216618.html 

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# 如果想用mysql数据库
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.mysql',
#         'NAME': 'dbname',
#         'USER':'root',
#         'PASSWORD': 'XXX',
#         'HOST':'',
#         'PORT':','
#     }
# }
settings.py设置数据库

 注意:如果需要使用mysql,但是我们之前使用的是pymysql,不是django默认的MySQLdb模块连接mysql,所以需要在project同名文件夹下的__init__.py文件下增加代码

import pymysql
pymysql.install_as_MySQLdb()

    2、根据类对数据库表中的数据进行各种操作

from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import redirect

# Create your views here.


def login(request):
    return HttpResponse('login')

from app01 import models
def orm(request):

    # 创建信息方法一(推荐使用)
    models.UserInfo.objects.create(
        username = 'root',
        password='123'
    )
    # 方法一可以写成
    # dic = {'username' : 'root','password':'123'}
    # models.UserInfo.objects.create(**dic)

    # 创建信息方法二
    # obj = models.UserInfo(username = 'root', password='123')
    # obj.save()
    return HttpResponse('orm')
创建数据
v = models.Business.objects.all()

# 查找特定的列,类似select id,caption from business
v = models.Business.objects.all().values('id','caption')
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import redirect

# Create your views here.


def login(request):
    return HttpResponse('login')

from app01 import models
def orm(request):

    # 创建信息方法一(推荐使用)
    # models.UserInfo.objects.create(
    #     username = 'root',
    #     password='123'
    # )
    # 方法一可以写成
    # dic = {'username' : 'root','password':'123'}
    # models.UserInfo.objects.create(**dic)

    # 创建信息方法二
    # obj = models.UserInfo(username = 'root', password='123')
    # obj.save()


    #
    # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
    # result = models.UserInfo.objects.all()
    # print(result)
    # for row in result:
    #     print(row.id,row.username,row.password)

    # 根据条件查出表里的数据,返回QuerySet类型
    result = models.UserInfo.objects.filter(username='root')
    for row in result:
        print(row.id, row.username, row.password)

    return HttpResponse('orm')
查询数据
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import redirect

# Create your views here.


def login(request):
    return HttpResponse('login')

from app01 import models
def orm(request):

    # 创建信息方法一(推荐使用)
    # models.UserInfo.objects.create(
    #     username = 'root',
    #     password='123'
    # )
    # 方法一可以写成
    # dic = {'username' : 'root','password':'123'}
    # models.UserInfo.objects.create(**dic)

    # 创建信息方法二
    # obj = models.UserInfo(username = 'root', password='123')
    # obj.save()


    #
    # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
    # result = models.UserInfo.objects.all()
    # print(result)
    # for row in result:
    #     print(row.id,row.username,row.password)

    # 根据条件查出表里的数据,返回QuerySet类型
    # result = models.UserInfo.objects.filter(username='root')
    # for row in result:
    #     print(row.id, row.username, row.password)


    # 删除
    # 删除表的所有数据
    models.UserInfo.objects.all().delete()

    # 删除表里id为1的数据
    models.UserInfo.objects.filter(id=1).delete()


    return HttpResponse('orm')
删除数据
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import redirect

# Create your views here.


def login(request):
    return HttpResponse('login')

from app01 import models
def orm(request):

    # 创建信息方法一(推荐使用)
    # models.UserInfo.objects.create(
    #     username = 'root',
    #     password='123'
    # )
    # 方法一可以写成
    # dic = {'username' : 'root','password':'123'}
    # models.UserInfo.objects.create(**dic)

    # 创建信息方法二
    # obj = models.UserInfo(username = 'root', password='123')
    # obj.save()


    #
    # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
    # result = models.UserInfo.objects.all()
    # print(result)
    # for row in result:
    #     print(row.id,row.username,row.password)

    # 根据条件查出表里的数据,返回QuerySet类型
    # result = models.UserInfo.objects.filter(username='root')
    # for row in result:
    #     print(row.id, row.username, row.password)


    # 删除
    # # 删除表的所有数据
    # models.UserInfo.objects.all().delete()
    #
    # # 删除表里id为1的数据
    # models.UserInfo.objects.filter(id=1).delete()


    # 更新
    # 表中所有数据的列password改为666
    models.UserInfo.objects.all().update(password=666)
    # 表中id为3 的行,password字段改为6669
    models.UserInfo.objects.filter(id=3).update(password=6669)

    return HttpResponse('orm')
改数据
from django.shortcuts import render

from app01 import models
# Create your views here.

def business(request):

    # 获取数据,保存为queryset列表
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business,返回的是字典
    v2 = models.Business.objects.all().values('id','caption')

    # 查询获取的结果,返回的是元组
    v3 = models.Business.objects.all().values_list('id','caption')

    return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
获取表单数据的三种方式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>业务线列表(对象)</h1>
        {% for row in v %}
            <ul>{{ row.id }}-{{ row.caption }}-{{ row.code }}</ul>
        {% endfor %}
     <h1>业务线列表(字典)</h1>
        {% for row in v2 %}
            <ul>{{ row.id }}-{{ row.caption }}</ul>
        {% endfor %}

    <h1>业务线列表(元组)</h1>
        {% for row in v3 %}
            <ul>{{ row.0 }}-{{ row.1 }}</ul>
        {% endfor %}

</body>
</html>
获取表单数据的三种方式.html

外键:

  

# 与表Business关联,to是关联的表,to_field是关联的字段
b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
如果没有明确写明主键,默认id就是外键
 当删除关联表中的数据时,当前表与其关联的行的行为
                                        - models.CASCADE,删除关联数据,与之关联也删除
                                        - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                                        - models.PROTECT,删除关联数据,引发错误ProtectedError
                                        - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                                        - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                                        - models.SET,删除关联数据,
                                                      a. 与之关联的值设置为指定值,设置:models.SET(值)
                                                      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)


from django.db import models

# Create your models here.

class Business(models.Model):

    # 没写id,所以django自动生成
    #
    caption = models.CharField(max_length=32)
    # 设置显示文字是英文还是中文;
    # null=True可以为空
    # default='默认值' 设置新增列的默认值
    code = models.CharField(max_length=32,null=True,default='默认值')


class Host(models.Model):

    # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
    nid = models.AutoField(primary_key=True)

    # 主机名,字符串,最大长度32位;db_index=True代表创建索引
    hostname = models.CharField(max_length=32,db_index=True)
    # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
    ip = models.GenericIPAddressField(protocol='both',db_index=True)
    # 端口,数字类型
    port = models.IntegerField()

    # 与表Business关联,to是关联的表,to_field是关联的字段
    b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
models.py

 用.(点)获取关联表信息

用双下划线__获取字符串里面的跨表信息

# 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
v2 = models.Business.objects.all().values('nid', 'hostname', 'b_id', 'b__caption')
print(type(v2))

创建多对多:

  方式一:自定义关系表

 

from django.db import models

# Create your models here.

class Business(models.Model):

    # 没写id,所以django自动生成
    #
    caption = models.CharField(max_length=32)
    # 设置显示文字是英文还是中文;
    # null=True可以为空
    # default='默认值' 设置新增列的默认值
    code = models.CharField(max_length=32,null=True,default='默认值')


class Host(models.Model):

    # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
    nid = models.AutoField(primary_key=True)

    # 主机名,字符串,最大长度32位;db_index=True代表创建索引
    hostname = models.CharField(max_length=32,db_index=True)
    # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
    ip = models.GenericIPAddressField(protocol='both',db_index=True)
    # 端口,数字类型
    port = models.IntegerField()

    # 与表Business关联,to是关联的表,to_field是关联的字段
    b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)


class Application(models.Model):
    '''
    应用
    '''
    name = models.CharField(max_length=32)



class HostToApp(models.Model):
    '''
    host app关联
    '''
    hobj = models.ForeignKey(to=Host,to_field='nid',on_delete=models.CASCADE)
    aobj = models.ForeignKey(to=Application,to_field='id',on_delete=models.CASCADE)
自定义关系表

  方式二:自动创建关系表

 缺点:无法直接对第三张表进行操作

  

from django.db import models

# Create your models here.

class Business(models.Model):

    # 没写id,所以django自动生成
    #
    caption = models.CharField(max_length=32)
    # 设置显示文字是英文还是中文;
    # null=True可以为空
    # default='默认值' 设置新增列的默认值
    code = models.CharField(max_length=32,null=True,default='默认值')


class Host(models.Model):

    # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
    nid = models.AutoField(primary_key=True)

    # 主机名,字符串,最大长度32位;db_index=True代表创建索引
    hostname = models.CharField(max_length=32,db_index=True)
    # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
    ip = models.GenericIPAddressField(protocol='both',db_index=True)
    # 端口,数字类型
    port = models.IntegerField()

    # 与表Business关联,to是关联的表,to_field是关联的字段
    b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)


class Application(models.Model):
    '''
    应用
    '''
    name = models.CharField(max_length=32)
    # 第三张表自动生成
    r = models.ManyToManyField('Host')
自动创建关系表

  obj = Application.objects.get(id=1)

  obj.name

若需要对第三表操作,则使用如下方法:

增加:

  obj.r.add(1)       增加关系1对1

  obj.r.add(2)       增加关系1对二

  obj.r.add(2,3,4)       增加关系1对2,1对3,1对4

  obj.r.add(*[1,2,3,4])   增加关系1对1,1对2,1对3,1对4

删除:

  obj.r.remove(1)         删除关系1对1

  obj.r.remove(2,4)      删除关系1对2,1对4

  obj.r.remove(*[1,2,3])     删除关系1对1,1对2,1对3

  obj.r.clear()        删除只要application是1的关系

  obj.r.set([3,5,7])      删除除了1对3,1对5,1对7之外所有的关系

获取:

  obj.r.all()        这里就是增加 b_list = models.Host.objects.all() 后面all的方法;obj.r相当于 models.Host.objects。

model操作补充

单表

1.修改表名;类下定义一个类,Meta

2.联合索引;

from django.db import models

# Create your models here.
class UserInfo(models.Model):
    nid = models.AutoField(primary_key=True)
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)

    class Meta:
        # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
        db_table = "table_name"

        # 联合索引
        # 最左前缀的模式:select * from table_name where username ='xx'
        # select * from table_name where username ='xx' and email = 'xx'
        # 前面两个都很快,但是如果没有了最左的那个,这里是uername,速度会非常慢
        index_together = [
            # ("pub_date", "deadline"),
            ("username", "email"),
        ]

        # 联合唯一索引
        unique_together = (("driver", "restaurant"),)

        # admin中显示的表名称,admin里面就会变成上课记录s
        verbose_name = '上课记录'

        # verbose_name加s,表名就会变成上课记录
        verbose_name_plural = '上课记录'
View Code

一对多,一对一,多对多

django现在的版本会对外键关联的表的数据都删除

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要进行关联的表名
        to_field=None,              # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                                        - models.CASCADE,删除关联数据,与之关联也删除
                                        - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                                        - models.PROTECT,删除关联数据,引发错误ProtectedError
                                        - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                                        - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                                        - models.SET,删除关联数据,
                                                      a. 与之关联的值设置为指定值,设置:models.SET(值)
                                                      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

                                                        def func():
                                                            return 10

                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据


    OneToOneField(ForeignKey)
        to,                         # 要进行关联的表名
        to_field=None               # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为

                                    ###### 对于一对一 ######
                                    # 1. 一对一其实就是 一对多 + 唯一索引
                                    # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                    # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)

                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

    ManyToManyField(RelatedField)
        to,                         # 要进行关联的表名
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                    # 做如下操作时,不同的symmetrical会有不同的可选字段
                                        models.BB.objects.filter(...)

                                        # 可选字段有:code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=True)

                                        # 可选字段有: bb, code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=False)

        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                        from django.db import models

                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)

                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through='Membership',
                                                through_fields=('group', 'person'),
                                            )

                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称
View Code
class UserType(models.Model):
    name = models.CharField(max_length=32)


class User(models.Model):

    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=64)
    ut = models.ForeignKey(
        to='UserType',
        to_field='id',
        on_delete=models.CASCADE
        )
# 正向操作
v = User.objects.all()
for item in v:
    item.user
    item.pwd
    item.ut.name

User.objects.all().values('user','ut__name')

# 反向操作
v = UserType.objects.all()
for item in v:
    item.name
    item.id
    # 当前类型对应的所有用户的集合
    item.user_set.all()
    
# 表名__字段  反向查找内容
UserType.objects.all().values('name','user__pwd')

如果加上related_name='b',反向查找就会将表名变更为b,如:UserType.objects.all().values('name','b__pwd')

Ajax:

参考:https://www.cnblogs.com/wupeiqi/articles/5703697.html

  建议:永远让服务器端返回一个字典,使用return HttpResponse(json.dumps(字典))

  不能用redirect

悄悄的提交,用Ajax

$.ajax({
    url:"/host",
    type:"POST"
    data:{"k1":123,"k2":"root"}
    success:function(data){
    //函数等服务器返回信息后,自动触发,返回的数据会放到data里,所以需要一个参数
    }
})

location.reload()         Jqery刷新页面
location.href = "某个地址"   跳转到其他页面

$.get(url='xxx',data={})
$.getJson
$.post

不管是哪个方法,都调用了$.ajax方法


ajax return的时候用HttpResponse()

js转换json

var obj = JSON.parse() 字符串转换为其他
JSON.stringfy() 转换为字符串

 traditional:true      允许发送列表

dataType:        写上这句,ajax会自动对接从服务器接收到的字符串反序列化

$(function () {
                $('#add_submit_ajax').click(function () {
                   $.ajax({
                       url:'/ajax_add_app',
{#                       data:{'user':123,'host_list':[1,2,3]},#}
                       data:$('#add_form').serialize(),
                       type:"POST",
{#                       允许发送列表#}
                       traditional:true,
{#                       写上这句就能让其自动反序列化,所以传递进入函数的就变成了对象#}
                       dataType:"JSON",
                       success:function (obj) {
                            console.log(obj)
                           location.reload()
                       },
{#                       若是拿去数据不成功的时候执行的函数#}
                       error:function () {

                       }
                   })
                });
}

 要想知道request对象里面有什么东西,就要知道这个对象是从哪个类生成的,然后查看对应类的函数,如type(request)查出对应类,然后导入查看

 

{#             若是要用POST方式发送的情况,必须要写上请求头说明发送的方式告知后端如何获取信息 #}
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" value="Ajax1" onclick="Ajax1()" />
    
    <script>
        function Ajax1() {
            var xhr = new XMLHttpRequest();
{#            指定发送方式,以及发送到哪里 true是否异步#}
            xhr.open('GET','/ajax_json/',true);
            xhr.onreadystatechange = function () {
                if(xhr.readyState = 4){
                    //有四种状态,当readyState等于4的时候就是接收数据完毕状态,显示对应的值
{#                    console.log(xhr.responseText);#}
                    var obj = JSON.parse(xhr.responseText);
                    console.log(obj);
                }
            };
{#            发送请求头#}
            xhr.setRequestHeader('k1','v1');
{#             若是要用POST方式发送的情况,必须要写上请求头说明发送的方式告知后端如何获取信息 #}
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
{#            发送数据#}
            xhr.send("name=root;pwd=123");
        }
    </script>
</body>
</html>
ajax.html
def ajax_json(request):
    ret = {'status':True,'data':None}
    import json
    return HttpResponse(json.dumps(ret))

发送文件时机: iframe =》jQuery(依赖FormData),XMLHttpRequest(FormData) 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .upload{
{#            position: absolute;#}
            display: inline-block;
            padding: 10px;
            background-color: brown;
            top:0;
            bottom: 0;
            right: 0;
            left:0;
            z-index:90;
        }
        .file{
            position: absolute;
            width: 100px;
            height: 50px;
            opacity: 0;
            top:0;
            bottom: 0;
            right: 0;
            left:0;
            z-index:100;
        }
    </style>
</head>
<body>
    <div style="position: relative; 100px;height: 50px;">
        <input class="file" type="file" id="fafa" name="ff" />
        <a class="upload">上传</a>
    </div>
    <input type="button" value=" 提交" onclick="xhrSubmit();" />
    <input type="button" value=" JQ提交" onclick="JQSubmit();" />

    <hr>
     <form action="/upload_file/" method="post"target="ifm1" enctype="multipart/form-data">
        {% csrf_token %}
        <iframe id="ifm1" name="ifm1"></iframe>
        <input type="file" name="fafa" />

        <input type="submit" onclick="iframeSubmit();" value="Form提交" />
    </form>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function JQSubmit() {
{#            $('#fafa')[0]相当于下面#}
{#            .files[0];代表要上传的文件对象#}
            var file_obj = document.getElementById('fafa').files[0];
            var fd = new FormData();
            fd.append('fafa',file_obj);
            fd.append('username','root');

            $.ajax({
                url:'/upload_file/',
                type:'POST',
                data:fd,
{#                processData:false, contentType:false,表名上传文件的时候不要做特殊处理,这样才能正确传递文件#}
                processData:false,
                contentType:false,
                sucess:function (arg,a1,a2) {
                    console.log(arg);
                    console.log(a1);
                    console.log(a2);
                }
            })
        }
         function xhrSubmit() {
{#            $('#fafa')[0]相当于下面#}
{#            .files[0];代表要上传的文件对象#}
            var file_obj = document.getElementById('fafa').files[0];
            var fd = new FormData();
            fd.append('fafa',file_obj);
            fd.append('username','root');

            var xhr = new XMLHttpRequest();
            xhr.open('POST','/upload_file/',true);
            xhr.onreadystatechange = function () {
                if(xhr.readyState = 4){
                    var obj = Json.parse(xhr.responseText);
                }
            };
            xhr.send(fd);
        }
{#       前面两种方法都存在浏览器兼容问题,而这个 iframe提交文件,兼容性强#}
         function iframeSubmit() {
            $('#ifm1').load(function () {
{#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);
            })
        }

    </script>
</body>
</html>
上传文件三种方式,iframe上传兼容性比较强

增加了预览图片,以及选中文件就上传


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .upload{
{#            position: absolute;#}
            display: inline-block;
            padding: 10px;
            background-color: brown;
            top:0;
            bottom: 0;
            right: 0;
            left:0;
            z-index:90;
        }
        .file{
            position: absolute;
            width: 100px;
            height: 50px;
            opacity: 0;
            top:0;
            bottom: 0;
            right: 0;
            left:0;
            z-index:100;
        }
    </style>
</head>
<body>
    <div style="position: relative; 100px;height: 50px;">
        <input class="file" type="file" id="fafa" name="ff" />
        <a class="upload">上传</a>
    </div>
    <input type="button" value=" 提交" onclick="xhrSubmit();" />
    <input type="button" value=" JQ提交" onclick="JQSubmit();" />

    <hr>
     <form id="fm1" action="/upload_file/" method="post"target="ifm1" enctype="multipart/form-data">
        {% csrf_token %}
        <iframe id="ifm1" name="ifm1" style="display: none"></iframe>
        <input type="file" name="fafa" onchange="changeUpload();"/>

        <input type="submit" onclick="iframeSubmit();" value="Form提交" />
    </form>


    <div id="preview">

    </div>



    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function changeUpload() {
            {#            让form表单改变就提交#}
            $('#ifm1').load(function () {
{#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);

{#                将原来的图片清空了,才能显示新图片#}
                $('#preview').empty();
{#                建立图片标签#}
                var imgTag = document.createElement('img');
{#                因为服务器传递过来的数据是没有前面的/,所以需要加上#}
                imgTag.src='/'+obj.data;
                $('#preview').append(imgTag);

            });

            $('#fm1').submit();
        }
        
        function JQSubmit() {
{#            $('#fafa')[0]相当于下面#}
{#            .files[0];代表要上传的文件对象#}
            var file_obj = document.getElementById('fafa').files[0];
            var fd = new FormData();
            fd.append('fafa',file_obj);
            fd.append('username','root');

            $.ajax({
                url:'/upload_file/',
                type:'POST',
                data:fd,
{#                processData:false, contentType:false,表名上传文件的时候不要做特殊处理,这样才能正确传递文件#}
                processData:false,
                contentType:false,
                sucess:function (arg,a1,a2) {
                    console.log(arg);
                    console.log(a1);
                    console.log(a2);
                }
            })
        }
         function xhrSubmit() {
{#            $('#fafa')[0]相当于下面#}
{#            .files[0];代表要上传的文件对象#}
            var file_obj = document.getElementById('fafa').files[0];
            var fd = new FormData();
            fd.append('fafa',file_obj);
            fd.append('username','root');

            var xhr = new XMLHttpRequest();
            xhr.open('POST','/upload_file/',true);
            xhr.onreadystatechange = function () {
                if(xhr.readyState = 4){
                    var obj = Json.parse(xhr.responseText);
                }
            };
            xhr.send(fd);
        }
{#       前面两种方法都存在浏览器兼容问题,而这个 iframe提交文件,兼容性强#}
         function iframeSubmit() {
            $('#ifm1').load(function () {
{#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);

{#                将原来的图片清空了,才能显示新图片#}
                $('#preview').empty();
{#                建立图片标签#}
                var imgTag = document.createElement('img');
{#                因为服务器传递过来的数据是没有前面的/,所以需要加上#}
                imgTag.src='/'+obj.data;
                $('#preview').append(imgTag);

            })
        }

    </script>
</body>
</html>
优化了的上传文件


from django.shortcuts import render,HttpResponse
from django import forms
from django.forms import fields
from django.forms import fields as Ffields
from app01 import models
# Create your views here.

# 避免跟modelform的属性冲突,更名为Fwidgets
from django.forms import widgets as Fwidgets
# # modelform方式
class UserInfoModelForm(forms.ModelForm):

    # 自定义字段,跟保存在数据库上没关系,例如一个月内免登陆的CheckBox
    is_rmb = Ffields.CharField(     widget=Fwidgets.CheckboxInput() )

    class Meta:
        # 这里指定字段对应的表
        model  =models.UserInfo
        # __all__代表多有的字段
        fields = '__all__'

        # 只显示的字段
        # fields = ['username','email']
        # 排除字段,其他的显示
        # exclude = ['email']
        # 显示标签更名
        labels = {
            'username':'用户名',
            'email':'邮箱'
        }
        #
        help_texts = {
            'username':'帮助信息'
        }
        # 将原来的CharField改为为Textarea
        widgets = {
            'username':Fwidgets.Textarea(attrs={'class':'c1'})
        }
        error_messages = {
            '__all__':'所有字段共同的错误',
            # email的错误信息
            'email':{
                'required':'邮箱不能为空',
                'invalid':'邮箱格式错误'

            }
        }
        # 更改格式,
        # field_classes = {
        #     # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
        #     'email': Ffields.URLField
        # }

# form方式
class UserInfoForm(forms.Form):
    # 定义字段
    username = fields.CharField(max_length=32,label='用户名')
    email = fields.EmailField(label='邮件')
    # 将数据库的id caption字段作为下拉显示
    user_type = fields.ChoiceField(
        choices = models.UserType.objects.values_list('id','caption'),
        label='类型'
    )
    def __init__(self,*args,**kwargs):
        super(UserInfoForm,self).__init__(*args,**kwargs)
        # 这样子就能更新数据库不需要重启程序就能更新数据
        self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')

def index(request):

    if request.method == 'GET':

        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoModelForm()

        return render(request,'index.html',{'obj':obj})
        # return render(request,'index.html')
    elif request.method == 'POST':
        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoModelForm(request.POST)
        if obj.is_valid():
            # obj.save()
            # 上面一句包含了下面三句代码,只不过默认传入commit=True
            instance = obj.save(False)
            instance.save()
            obj.save_m2m()
        # print(obj.is_valid())
        # print(obj.cleaned_data)
        # print(obj.errors)
        # obj.cleaned_data

        return render(request, 'index.html', {'obj': obj})



def user_list(request):

    li = models.UserInfo.objects.all().select_related('user_type')
    return render(request,'user_list.html',{'li':li})


def user_edit(request,nid):
    # 获取当前id对象的用户信息
    # 显示用户已经存在的数据
    if request.method == "GET":
        user_obj = models.UserInfo.objects.filter(id=nid).first()
        mf = UserInfoModelForm(instance=user_obj)
        return render(request,'user_edit.html',{'mf':mf,'nid':nid})
    elif request.method == 'POST':
        user_obj = models.UserInfo.objects.filter(id=nid).first()
        # instance=user_obj)告诉数据库要更新的是哪个对象
        mf = UserInfoModelForm(request.POST,instance=user_obj)
        if mf.is_valid():
            mf.save()

        else:
            print(mf.errors.as_json())
        return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})

def ajax(request):
    return render(request,'ajax.html')


def ajax_json(request):
    ret = {'status':True,'data':request.POST.get('username')}
    import json
    return HttpResponse(json.dumps(ret))


def upload(request):
    return render(request,'upload.html')

def upload_file(request):

    username = request.POST.get('username')
    fafa = request.FILES.get('fafa')
    import os
    img_path = os.path.join('static','imgs',fafa.name)
    print(img_path)
    # img_path = fafa.name

    with open(img_path,'wb') as f:
        for item in fafa.chunks():
            f.write(item)
    ret = {'code':True,'data':img_path}

    print(username,fafa)
    import json
    return HttpResponse(json.dumps(ret))
views.py

session+验证码图片

1.创建一张图片

2.在图片中写入随机字符串

3.将图片写入到指定文件中

4.打开制定目录文件,读取内容

5.HTTPResponse(data)

需要用到session,check_code.py(依赖:Pillow,字体文件),点一次就变化的话,需要src属性后面加?




HTML模板继承

注意:只能继承一个模板

头顶要写上继续哪个模板 {% extends '模板名 %}

 {% extends 'master.html' %}

 被继承的模板写成:{% block 模板名%}  {% endblock %}

{% block content %} {% endblock %}

继承的模板写成  (block模块位置是没所谓的)
{% block 模板名%} 替换的内容 {% endblock %}

 

 模板的导入(导入可以导入多个模板)

{% include '模板名' %}
{% include 'tag.html' %}
<form>
    <input type="text" />
    <input type="submit" />
</form>
tag.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% include 'tag.html' %}
    {% include 'tag.html' %}

</body>
</html>
index.html
django自带的方法:  
帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}} 
{{ bio|truncatewords:"30" }}         # 获取前30个字符,进行分割
{{ my_list|first|upper }}           # 第一个字符转换为大写
{{ name|lower }}                #转换为小写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<p></p>
    {{ name }}
<div></div>
    {{ name | lower }}
</body>
</html>
例子

自定义simple_tag

  优点:参数任意

  缺点:不能作为if条件

  1.在某个APP目录下创建一个目录templatetags(必须是这个名字)

  2.templatetags目录下创建.py文件

  3.创建template对象 必须为register  请参考下面代码

  

from django import template
from django.utils.safestring import mark_safe

# 装饰器,名字不能修改,必须为register
register  = template.Library()

@register.simple_tag
def houyafan(a1,a2):
    return a1 + a2
xxoo.py

  4.settings注册app

 

   5.HTML文件顶部写上{% load py文件名 %}:  {% load xxoo %}

   6.{% 函数名 参数a1 参数a2 %}  {% houyafan 2 5 %}

自定义simple_filter

优点:能作为if条件

缺点:参数任意,不能加空格

步骤与simple_tag一样,

 写法:

{{ '参数1'|函数名:'参数2,参数三' }}
{{ '字符串'|filter_test:'相加,参数三' }}
from django import template
from django.utils.safestring import mark_safe

# 装饰器,名字不能修改,必须为register
register  = template.Library()

# filter最多传递两个值
@register.filter
def filter_test(a1,a2):
    return a1 + a2
View Code
{% load xxoo %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% houyafan 2 5 %}
{#    不能加空格#}
     {{ '字符串'|filter_test:'相加' }}
{#    如果需要传递三个以上参数,只能这样弄#}
{#    这种方式一般用于if else里面#}
     {{ '字符串'|filter_test:'相加,参数三' }}

    {%  if '字符串'|filter_test:'相加' %}
        显示
    {% endif %}


{#    {% include 'tag.html' %}#}
{#    {% include 'tag.html' %}#}
{#<p></p>#}
{#    {{ name }}#}
{#<div></div>#}
{#    {{ name | lower }}#}
</body>
</html>
index.html

分页

XSS攻击:默认传递带有HTML语言的字符串是不安全的,不会做解析
后端需要加上
from django.utils.safestring import mark_safe
page_str='''<a href="/user_list/?p=2">1 </a>'''
page_str = mark_safe(page_str)

前端需要这样写

{{ page_str|safe }}

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

from app01 import models
import json
# Create your views here.

def business(request):

    # 获取数据,保存为queryset列表
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business,返回的是字典
    v2 = models.Business.objects.all().values('id','caption')

    # 查询获取的结果,返回的是元组
    v3 = models.Business.objects.all().values_list('id','caption')


    return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})


def host(request):
    if request.method == "GET":
        v = models.Business.objects.filter(host__nid__gt=0)
        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
        # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
        # print(type(v2))
        # for row in v2:
        #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])

        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
        # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
        # print(type(v3))

        b_list = models.Host.objects.all()
        for row in b_list:
            print(row.hostname)

        return render(request, 'host.html', {"v": v,'b_list':b_list})
    # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})

    elif request.method == 'POST':
        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)

        models.Host.objects.create(hostname = h,
                                   ip = i,
                                   port = p,
                                   b_id = b
                                   )

        return redirect('/host/')


def test_ajax(request):
    # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
    # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))

    ret = {'status': True, 'error': None, 'data': None}
    try:

        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)
        if h and len(h) > 5:
            models.Host.objects.create(hostname=h,
                                       ip=i,
                                       port=p,
                                       b_id=b
                                       )

        else:
            ret['status'] = False
            ret['error'] = '太短了'


    except Exception as e:
        ret['status'] = False
        ret['error'] = '请求错误'
    return HttpResponse(json.dumps(ret))


def app(request):
    if request.method == 'GET':
        app_list = models.Application.objects.all()
        for row in app_list:
            print(row.name,row.r.all())

        host_list = models.Host.objects.all()
        return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
    elif request.method == 'POST':
        app_name = request.POST.get('app_name')
        host_list = request.POST.getlist('host_list')
        print(app_name,host_list)

        obj = models.Application.objects.create(name = app_name)
        obj.r.add(*host_list)

        return redirect('/app/')

def ajax_add_app(request):
    ret = {'status':True,'error':None,"data":None}
    app_name = request.POST.get('app_name')
    host_list =request.POST.getlist('host_list')
    obj = models.Application.objects.create(name=app_name)
    obj.r.add(*host_list)



    return HttpResponse(json.dumps(ret))


def index(request):
    name = 'QWERTYU'
    return render(request,'index.html',{'name':name})

LIST = []
for i in range(109):
    LIST.append(i)

def user_list(request):
    #  当前页,获取p的值,若没有值的时候,默认为1
    current_page = request.GET.get('p',1)
    # 传递过来的是字符串,这边是数字计算的
    current_page = int(current_page)
    start = (current_page-1) * 10
    end = current_page * 10

    li = LIST[start:end]

    all_count = len(LIST)
    # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    count,y = divmod(all_count,10)
    # 如果有余数,分页数需要+1
    if y:
        count +=1

    page_list = []
    for i in range(1,count+1):
        # 如果i等于当前页。将当前页颜色变一下
        if i == current_page:
            temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
        else:
            temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
        page_list.append(temp)

    page_str = " ".join(page_list)
    page_str = mark_safe(page_str)

    return render(request,'user_list.html',{'li':li,'page_str':page_str})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pagenation .page{
            display: inline-block;
            padding: 5px;
            background-color: grey;
            margin: 5px;
        }
         .pagenation .page.active{
             background-color: brown;
             color: white;
         }
    </style>
</head>
<body>
    <ul>
        {% for item in li %}
           {% include 'li.html' %}
        {% endfor %}
    </ul>
    <div class="pagenation">
        {{ page_str }}
    </div>



</body>
</html>
user_list.html
"""day20 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

from django.conf.urls import url
from app01 import views
urlpatterns = [

    url(r'^user_list/$', views.user_list),

]
urls.py
from django.shortcuts import render,HttpResponse
from django.shortcuts import redirect
from django.utils.safestring import mark_safe

from app01 import models
import json
# Create your views here.

def business(request):

    # 获取数据,保存为queryset列表
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business,返回的是字典
    v2 = models.Business.objects.all().values('id','caption')

    # 查询获取的结果,返回的是元组
    v3 = models.Business.objects.all().values_list('id','caption')


    return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})


def host(request):
    if request.method == "GET":
        v = models.Business.objects.filter(host__nid__gt=0)
        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
        # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
        # print(type(v2))
        # for row in v2:
        #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])

        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
        # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
        # print(type(v3))

        b_list = models.Host.objects.all()
        for row in b_list:
            print(row.hostname)

        return render(request, 'host.html', {"v": v,'b_list':b_list})
    # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})

    elif request.method == 'POST':
        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)

        models.Host.objects.create(hostname = h,
                                   ip = i,
                                   port = p,
                                   b_id = b
                                   )

        return redirect('/host/')


def test_ajax(request):
    # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
    # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))

    ret = {'status': True, 'error': None, 'data': None}
    try:

        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)
        if h and len(h) > 5:
            models.Host.objects.create(hostname=h,
                                       ip=i,
                                       port=p,
                                       b_id=b
                                       )

        else:
            ret['status'] = False
            ret['error'] = '太短了'


    except Exception as e:
        ret['status'] = False
        ret['error'] = '请求错误'
    return HttpResponse(json.dumps(ret))


def app(request):
    if request.method == 'GET':
        app_list = models.Application.objects.all()
        for row in app_list:
            print(row.name,row.r.all())

        host_list = models.Host.objects.all()
        return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
    elif request.method == 'POST':
        app_name = request.POST.get('app_name')
        host_list = request.POST.getlist('host_list')
        print(app_name,host_list)

        obj = models.Application.objects.create(name = app_name)
        obj.r.add(*host_list)

        return redirect('/app/')

def ajax_add_app(request):
    ret = {'status':True,'error':None,"data":None}
    app_name = request.POST.get('app_name')
    host_list =request.POST.getlist('host_list')
    obj = models.Application.objects.create(name=app_name)
    obj.r.add(*host_list)



    return HttpResponse(json.dumps(ret))


def index(request):
    name = 'QWERTYU'
    return render(request,'index.html',{'name':name})

LIST = []
for i in range(500):
    LIST.append(i)

# def user_list(request):
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         count +=1
#
#     page_list = []
#     for i in range(1,count+1):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)
#
#     return render(request,'user_list.html',{'li':li,'page_str':page_str})
def user_list(request):
    #  当前页,获取p的值,若没有值的时候,默认为1
    current_page = request.GET.get('p',1)
    # 传递过来的是字符串,这边是数字计算的
    current_page = int(current_page)
    start = (current_page-1) * 10
    end = current_page * 10

    li = LIST[start:end]

    all_count = len(LIST)
    # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    total_count,y = divmod(all_count,10)
    # 如果有余数,分页数需要+1
    if y:
        total_count +=1

    page_list = []
    # 显示页面当前页的前后五页
    # start_index = current_page - 5
    # end_index = current_page + 5 +1
    if total_count < 11:
        start_index = 0
        end_index = total_count

    else:
        if current_page <= 6 :
            start_index = 1
            end_index = 11
        else:
            start_index = current_page - 5
            end_index = current_page +5 +1
            if (current_page + 5) > total_count:
                start_index  = total_count - 11 +1
                end_index = total_count +1


    for i in range(start_index,end_index):
        # 如果i等于当前页。将当前页颜色变一下
        if i == current_page:
            temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
        else:
            temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
        page_list.append(temp)

    page_str = " ".join(page_list)
    page_str = mark_safe(page_str)

    return render(request,'user_list.html',{'li':li,'page_str':page_str})
优化版,11
from django.shortcuts import render,HttpResponse
from django.shortcuts import redirect
from django.utils.safestring import mark_safe

from app01 import models
import json
# Create your views here.

def business(request):

    # 获取数据,保存为queryset列表
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business,返回的是字典
    v2 = models.Business.objects.all().values('id','caption')

    # 查询获取的结果,返回的是元组
    v3 = models.Business.objects.all().values_list('id','caption')


    return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})


def host(request):
    if request.method == "GET":
        v = models.Business.objects.filter(host__nid__gt=0)
        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
        # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
        # print(type(v2))
        # for row in v2:
        #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])

        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
        # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
        # print(type(v3))

        b_list = models.Host.objects.all()
        for row in b_list:
            print(row.hostname)

        return render(request, 'host.html', {"v": v,'b_list':b_list})
    # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})

    elif request.method == 'POST':
        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)

        models.Host.objects.create(hostname = h,
                                   ip = i,
                                   port = p,
                                   b_id = b
                                   )

        return redirect('/host/')


def test_ajax(request):
    # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
    # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))

    ret = {'status': True, 'error': None, 'data': None}
    try:

        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)
        if h and len(h) > 5:
            models.Host.objects.create(hostname=h,
                                       ip=i,
                                       port=p,
                                       b_id=b
                                       )

        else:
            ret['status'] = False
            ret['error'] = '太短了'


    except Exception as e:
        ret['status'] = False
        ret['error'] = '请求错误'
    return HttpResponse(json.dumps(ret))


def app(request):
    if request.method == 'GET':
        app_list = models.Application.objects.all()
        for row in app_list:
            print(row.name,row.r.all())

        host_list = models.Host.objects.all()
        return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
    elif request.method == 'POST':
        app_name = request.POST.get('app_name')
        host_list = request.POST.getlist('host_list')
        print(app_name,host_list)

        obj = models.Application.objects.create(name = app_name)
        obj.r.add(*host_list)

        return redirect('/app/')

def ajax_add_app(request):
    ret = {'status':True,'error':None,"data":None}
    app_name = request.POST.get('app_name')
    host_list =request.POST.getlist('host_list')
    obj = models.Application.objects.create(name=app_name)
    obj.r.add(*host_list)



    return HttpResponse(json.dumps(ret))


def index(request):
    name = 'QWERTYU'
    return render(request,'index.html',{'name':name})

LIST = []
for i in range(500):
    LIST.append(i)

# def user_list(request):
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         count +=1
#
#     page_list = []
#     for i in range(1,count+1):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)
#
#     return render(request,'user_list.html',{'li':li,'page_str':page_str})
# def user_list(request):
#     '''
#     特定为10页的时候
#     :param request:
#     :return:
#     '''
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     total_count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         total_count +=1
#
#     page_list = []
#     # 显示页面当前页的前后五页
#     # start_index = current_page - 5
#     # end_index = current_page + 5 +1
#     if total_count < 11:
#         start_index = 0
#         end_index = total_count
#
#     else:
#         if current_page <= 6 :
#             start_index = 1
#             end_index = 11
#         else:
#             start_index = current_page - 5
#             end_index = current_page +5 +1
#             if (current_page + 5) > total_count:
#                 start_index  = total_count - 11 +1
#                 end_index = total_count +1
#
#
#     for i in range(start_index,end_index):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)
#
#     return render(request,'user_list.html',{'li':li,'page_str':page_str})
def user_list(request):
    '''

    :param request:
    :return:
    '''
    #  当前页,获取p的值,若没有值的时候,默认为1
    current_page = request.GET.get('p',1)
    # 传递过来的是字符串,这边是数字计算的
    current_page = int(current_page)
    start = (current_page-1) * 10
    end = current_page * 10

    li = LIST[start:end]

    all_count = len(LIST)
    # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    total_count,y = divmod(all_count,10)
    # 如果有余数,分页数需要+1
    if y:
        total_count +=1

    page_list = []
    # 显示页码多少个,这里是11,建议使用基数
    perpage_num = 11
    # 显示页面当前页的前后五页
    # start_index = current_page - 5
    # end_index = current_page + 5 +1
    if total_count < perpage_num:
        start_index = 0
        end_index = total_count

    else:
        if current_page <= (perpage_num+1)/2 :
            start_index = 1
            end_index = perpage_num
        else:
            start_index = current_page - (perpage_num-1)/2
            end_index = current_page +(perpage_num-1)/2 +1
            if (current_page + (perpage_num-1)/2) > total_count:
                start_index  = total_count - perpage_num +1
                end_index = total_count +1
    if current_page ==1:
        # javascript:void(0);这个代表什么都不干
        prev = '<a class="page active"  href="javascript:void(0);">上一页</a>'
    else:
        prev = '<a class="page active"  href="/user_list/?p=%s">上一页</a>' %(current_page-1)
    page_list.append(prev)

    for i in range(int(start_index),int(end_index)):
        # 如果i等于当前页。将当前页颜色变一下
        if i == current_page:
            temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
        else:
            temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
        page_list.append(temp)
    if current_page == total_count:
        nex = '<a class="page active"  href="javascript:void(0)">下一页</a>'
    else:
        nex = '<a class="page active"  href="/user_list/?p=%s">下一页</a>' % (current_page + 1)
    page_list.append(nex)
    # 跳转
    jump = '''
    <input type = 'text'/><a onclick='jumpTo(this,"/user_list/?p=");'id='ii1'>GO</a>
    <script>
        function jumpTo(ths,base){
            var val = ths.previousSibling.value;
            location.href = base + val;
        }
    </script>
    
    '''
    page_list.append(jump)

    page_str = " ".join(page_list)
    page_str = mark_safe(page_str)

    return render(request,'user_list.html',{'li':li,'page_str':page_str})
优化版——多了上一页、下一页,跳转
from django.utils.safestring import mark_safe

class Page:
    def __init__(self,current_page,data_count,per_page_count = 10, pager_num = 7):
        '''

        :param current_page: 当前页
        :param data_count: 分页总数
        :param per_page_count: 每一页显示多少行,这里默认10行
        :param pager_num: 分页显示多少页,这里默认7页
        '''
        self.current_page = current_page
        self.data_count = data_count
        self.per_page_count = per_page_count
        self.pager_num = pager_num
    # @property意思是将方法变成属性,不再需要写括号
    @property
    def start(self):
        '''
        分割总行数的开始
        :return:
        '''
        return (self.current_page - 1) * self.per_page_count
    @property
    def end(self):
        '''
        分割总行数的结束
        :return:
        '''
        return self.current_page * self.per_page_count
    @property
    def total_count(self):
        '''
        计算分页页数
        :return:
        '''
        # divmod是将data_count除以per_page_count,计算出值余多少,值传入v,余数传入y
        v,y = divmod(self.data_count,self.per_page_count)
        # 如果有余数,需要增加一页分页
        if y:
            v +=1
        return v

    def page_str(self,base_url):
        '''

        :param base_url:跳转的地址
        :return:
        '''
        # 传递到前端的列表,用于保存数据
        page_list = []
        # 如果分页总数少于默认的7页,就显示所有分页
        if self.total_count < self.per_page_count:
            start_index = 1
            end_index = self.total_count + 1

        else:
            # 如果当前页在显示分页数的一半内
            if self.current_page <= (self.pager_num + 1)/2:
                start_index = 1
                end_index = self.pager_num + 1

            else:
                start_index = self.current_page - (self.pager_num -1)/2
                end_index = self.current_page + (self.pager_num + 1)/2
                # 处理最后的分页,如果当前页+默认显示页的一半大于总分页数,不会再向后增加页数
                if (self.current_page + (self.pager_num -1)/2) > self.total_count:
                    start_index = self.total_count - self.pager_num +1
                    end_index = self.total_count +1

        # 当前页是第一页的情况,上一页失效
        if self.current_page == 1:
            prev = '<a class="page"  href="javascript:void(0);">上一页</a>'
        else:
            prev = '<a class="page"   href="%s?p=%s">上一页</a>' %(base_url,self.current_page-1)
        page_list.append(prev)

        for i in range(int(start_index),int(end_index)):
            # 当前页显示的分页样式不一样
            if i == self.current_page:
                temp = '<a class="page active"  href="%s?p=%s">%s</a>' % (base_url, i,i)

            else:
                temp = '<a class="page"  href="%s?p=%s">%s</a>' % (base_url, i,i)

            page_list.append(temp)

        if self.current_page == self.total_count:
            nex = '<a class="page"  href="javascript:void(0);">下一页</a>'
        else:
            nex = '<a class="page"   href="%s?p=%s">下一页</a>' %(base_url,self.current_page+1)

        page_list.append(nex)

        jump = '''
        <input type = 'text'/><a onclick='jumpTo(this,"%s?p=");'id='ii1'>GO</a>
        <script>
            function jumpTo(ths,base){
                var val = ths.previousSibling.value;
                location.href = base + val;
            }
        </script>

        '''%(base_url)
        page_list.append(jump)

        page_str = mark_safe(" ".join(page_list))
        return page_str
pagination(分页)
LIST = []
for i in range(500)
    LIST.append(i)
def user_list(request):
    current_age = request.GET.get('p',1)
    current_age = int(current_age)
    page_obj = Page(current_age,len(LIST))
    data = LIST[page_obj.start,page_obj.end]
    page_str = page_obj.page_str('/user_list/')
    return render(request,'user_list.html',{'li':data,'page_str':page_str})
views.py

cookie

 客户端浏览器上的一个文件

cookie的简单应用

res = redirect('/index/')
# 设定cookie user 为u
res.set_cookie('user111',u)    #res.set_cookie('key','value'),默认情况下,关闭浏览器cookie就失效
# 获取当前已经登陆的用户信息
v = request.COOKIES.get('user111')

rep = HttpResponse(...) 或 rep = render(request, ...)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间,秒多少秒之后失效
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)指定某个时间超时
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

 

  引入jquery的cookie插件
  <script src="/static/jquery-1.12.4.js"></script>

{# 必须在引入jQuery后面写 #}
<script src="/static/jquery.cookie.js"></script>

  就能使用$.cookie()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pagenation .page{
            display: inline-block;
            padding: 5px;
            background-color: grey;
            margin: 5px;
        }
         .pagenation .page.active{
             background-color: brown;
             color: white;
         }
    </style>
</head>
<body>
    <ul>
        {% for item in li %}
           {% include 'li.html' %}
        {% endfor %}
    </ul>
    <div>
        <select id="s1" onchange="changePageSize(this)">
            <option value="10">10</option>
            <option value="30">30</option>
            <option value="50">50</option>
            <option value="100">100</option>
        </select>
    </div>
    <div class="pagenation">
        {{ page_str }}
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
{#    必须在引入jQuery后面写 #}
    <script src="/static/jquery.cookie.js"></script>

    <script>
        $(function(){
{#            {'path': "/user_list/`"});加入这个就,就能使得对当前url有影响,其他的不影响#}
                var v = $.cookie('per_page_count', {'path': "/user_list/`"});
                $('#ps').val(v);
        });

        function changePageSize(ths){
            var v = $(ths).val();
            console.log(v);
            $.cookie('per_page_count',v, {'path': "/user_list/"});

            location.reload();
        }
{#        $(function () {#}
{#           var v = $.cookie('per_page_count');#}
{#            var v = document.cookie('per_page_count');#}
{#            $('#s1').val(v);#}
{#        });#}
{##}
{#        function changePageSize(ths) {#}
{#            var v = $(ths).val();#}
{#            var v = $('#s1').val();#}
{#            console.log(v);#}
{#            $.cookie('per_page_count',v);#}
{#            temp = 'per_page_count'+v +';';#}
{#            console.log(temp);#}
{#            document.cookie = temp;#}
{##}
{#            刷新#}
{#            location.reload();#}
{#        }#}
    </script>



</body>
</html>
user_list.html(cookie影响分页)
from django.shortcuts import render,HttpResponse
from django.shortcuts import redirect
from django.utils.safestring import mark_safe

from app01 import models
from utils import pagination
import json
# Create your views here.

def business(request):

    # 获取数据,保存为queryset列表
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business,返回的是字典
    v2 = models.Business.objects.all().values('id','caption')

    # 查询获取的结果,返回的是元组
    v3 = models.Business.objects.all().values_list('id','caption')


    return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})


def host(request):
    if request.method == "GET":
        v = models.Business.objects.filter(host__nid__gt=0)
        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
        # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
        # print(type(v2))
        # for row in v2:
        #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])

        # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
        # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
        # print(type(v3))

        b_list = models.Host.objects.all()
        for row in b_list:
            print(row.hostname)

        return render(request, 'host.html', {"v": v,'b_list':b_list})
    # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})

    elif request.method == 'POST':
        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)

        models.Host.objects.create(hostname = h,
                                   ip = i,
                                   port = p,
                                   b_id = b
                                   )

        return redirect('/host/')


def test_ajax(request):
    # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
    # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))

    ret = {'status': True, 'error': None, 'data': None}
    try:

        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
        print(h)
        print(i)
        print(p)
        print(b)
        if h and len(h) > 5:
            models.Host.objects.create(hostname=h,
                                       ip=i,
                                       port=p,
                                       b_id=b
                                       )

        else:
            ret['status'] = False
            ret['error'] = '太短了'


    except Exception as e:
        ret['status'] = False
        ret['error'] = '请求错误'
    return HttpResponse(json.dumps(ret))


def app(request):
    if request.method == 'GET':
        app_list = models.Application.objects.all()
        for row in app_list:
            print(row.name,row.r.all())

        host_list = models.Host.objects.all()
        return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
    elif request.method == 'POST':
        app_name = request.POST.get('app_name')
        host_list = request.POST.getlist('host_list')
        print(app_name,host_list)

        obj = models.Application.objects.create(name = app_name)
        obj.r.add(*host_list)

        return redirect('/app/')

def ajax_add_app(request):
    ret = {'status':True,'error':None,"data":None}
    app_name = request.POST.get('app_name')
    host_list =request.POST.getlist('host_list')
    obj = models.Application.objects.create(name=app_name)
    obj.r.add(*host_list)



    return HttpResponse(json.dumps(ret))




LIST = []
for i in range(500):
    LIST.append(i)

# def user_list(request):
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         count +=1
#
#     page_list = []
#     for i in range(1,count+1):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)
#
#     return render(request,'user_list.html',{'li':li,'page_str':page_str})
# def user_list(request):
#     '''
#     特定为10页的时候
#     :param request:
#     :return:
#     '''
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     total_count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         total_count +=1
#
#     page_list = []
#     # 显示页面当前页的前后五页
#     # start_index = current_page - 5
#     # end_index = current_page + 5 +1
#     if total_count < 11:
#         start_index = 0
#         end_index = total_count
#
#     else:
#         if current_page <= 6 :
#             start_index = 1
#             end_index = 11
#         else:
#             start_index = current_page - 5
#             end_index = current_page +5 +1
#             if (current_page + 5) > total_count:
#                 start_index  = total_count - 11 +1
#                 end_index = total_count +1
#
#
#     for i in range(start_index,end_index):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)
#
#     return render(request,'user_list.html',{'li':li,'page_str':page_str})
# def user_list(request):
#     '''
#
#     :param request:
#     :return:
#     '''
#     #  当前页,获取p的值,若没有值的时候,默认为1
#     current_page = request.GET.get('p',1)
#     # 传递过来的是字符串,这边是数字计算的
#     current_page = int(current_page)
#     start = (current_page-1) * 10
#     end = current_page * 10
#
#     li = LIST[start:end]
#
#     all_count = len(LIST)
#     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
#     total_count,y = divmod(all_count,10)
#     # 如果有余数,分页数需要+1
#     if y:
#         total_count +=1
#
#     page_list = []
#     # 显示页码多少个,这里是11,建议使用基数
#     perpage_num = 11
#     # 显示页面当前页的前后五页
#     # start_index = current_page - 5
#     # end_index = current_page + 5 +1
#     if total_count < perpage_num:
#         start_index = 0
#         end_index = total_count
#
#     else:
#         if current_page <= (perpage_num+1)/2 :
#             start_index = 1
#             end_index = perpage_num
#         else:
#             start_index = current_page - (perpage_num-1)/2
#             end_index = current_page +(perpage_num-1)/2 +1
#             if (current_page + (perpage_num-1)/2) > total_count:
#                 start_index  = total_count - perpage_num +1
#                 end_index = total_count +1
#     if current_page ==1:
#         # javascript:void(0);这个代表什么都不干
#         prev = '<a class="page active"  href="javascript:void(0);">上一页</a>'
#     else:
#         prev = '<a class="page active"  href="/user_list/?p=%s">上一页</a>' %(current_page-1)
#     page_list.append(prev)
#
#     for i in range(int(start_index),int(end_index)):
#         # 如果i等于当前页。将当前页颜色变一下
#         if i == current_page:
#             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
#         else:
#             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
#         page_list.append(temp)
#     if current_page == total_count:
#         nex = '<a class="page active"  href="javascript:void(0)">下一页</a>'
#     else:
#         nex = '<a class="page active"  href="/user_list/?p=%s">下一页</a>' % (current_page + 1)
#     page_list.append(nex)
#     # 跳转
#     jump = '''
#     <input type = 'text'/><a onclick='jumpTo(this,"/user_list/?p=");'id='ii1'>GO</a>
#     <script>
#         function jumpTo(ths,base){
#             var val = ths.previousSibling.value;
#             location.href = base + val;
#         }
#     </script>
#
#     '''
#     page_list.append(jump)
#
#     page_str = " ".join(page_list)
#     page_str = mark_safe(page_str)

    # return render(request,'user_list.html',{'li':li,'page_str':page_str})

def user_list(request):
    current_page = request.GET.get('p', 1)
    current_page = int(current_page)

    val = request.COOKIES.get('per_page_count')
    print(val)
    page_obj = pagination.Page(current_page, len(LIST),val)
    data = LIST[page_obj.start:page_obj.end]
    page_str = page_obj.page_str("/user_list/")
    # data = [4,5,6]
    # page_str = [1,2,3]
    return render(request, 'user_list.html', {'li': data, 'page_str': page_str})

user_info = {
    'user':{"pwd":"123"}
}
def index(request):
    # 获取当前已经登陆的用户信息
    v = request.COOKIES.get('user111')
    if not v:
        return redirect('/login/')

    return render(request,'index.html',{'name':v})

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        u = request.POST.get('user')
        p = request.POST.get('pwd')
        dic = user_info.get(u)
        if not dic:
            return render(request,'login.html')
        if dic['pwd'] == p:
            res = redirect('/index/')
            # 设定cookie user 为u
            res.set_cookie('user111',u)
            res.set_cookie('key','value')
            return res
        else:
            return render(request,'login.html')
views.py

带签名的cookie

 基于cookie做用户验证时,不适合存放敏感信息,例如账号密码,银行余额等

优点:存储数据的压力放到客户端上

FVB与MVB装饰器实现用户认证

def auth(func):
    '''
    装饰器,如果发现cookie存储的不是用户名,则需要用户登录
    :param func:
    :return:
    '''
    def inner(request,*args,**kwargs):
        # 获取当前已经登陆的用户信息
        v = request.COOKIES.get('user111')
        if not v:
            return redirect('login')
        return func(request,*args,**kwargs)
    return inner

@auth
def index(request):
    # 获取当前已经登陆的用户信息,因为写了装饰器,所以不需要了
    v = request.COOKIES.get('user111')
    if not v:
        return redirect('/login/')

    return render(request,'index.html',{'name':v})
FVB装饰器
CBV
def auth(func):
    '''
    装饰器,如果发现cookie存储的不是用户名,则需要用户登录
    :param func:
    :return:
    '''
    def inner(request,*args,**kwargs):
        # 获取当前已经登陆的用户信息
        v = request.COOKIES.get('user111')
        if not v:
            return redirect('login')
        return func(request,*args,**kwargs)
    return inner



from django import views
from django.utils.decorators import method_decorator

# 在类上面写上这个@method_decorator(auth,name="dispatch")。相当于,在下写了第一个继承的函数
@method_decorator(auth,name="dispatch")
class Order(views.View):
    
    # 这里写一个之后,因为所有函数都先执行dispatch的,所以就类里面的所有函数都需要验证
    @method_decorator(auth)
    def dispatch(self, request, *args, **kwargs):
        return super(Order,self).dispatch(request, *args, **kwargs)

    # 写在方法上,是单独对这个方法使用验证
    @method_decorator(auth)
    def get(self,request):
        # 获取当前已经登陆的用户信息
        v = request.COOKIES.get('user111')

        return render(request, 'index.html', {'name': v})
    def post(self,request):
        # 获取当前已经登陆的用户信息
        v = request.COOKIES.get('user111')
        return render(request, 'index.html', {'name': v})
装饰器

session

  cookie是保存在用户浏览器端的键值对

  session是保存在服务器端的键值对

   session依赖于cookie

注意:使用session之前,必须要进入到对应目录下执行代码

python manage.py makemigrations

python manage.py migrate

session的id默认情况下Django的放在数据库里面的

session默认存在两周

建立session:

# 生成随机字符串
# 写到用户浏览器cookie
# 保存到session中
# 在随机字符串对应的字典中设置相关内容
request.session['username'] = user    #设置session
request.session['username']        #获取session

服务器session
  request.session.get('username',None)  #获取session,如果不存在,默认设置为None
  request.session.clear           #用于注销,删除当前cookie
在配置文件中设置默认操作,放在settings.py
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

from django.shortcuts import render,redirect,HttpResponse

# Create your views here.

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')

    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'root' and pwd == '123':
            # 生成随机字符串
            # 写到用户浏览器cookie
            # 保存到session中
            # 在随机字符串对应的字典中设置相关内容
            request.session['username'] = user
            request.session['is_login'] = True
            return  redirect('/index/')

        else:
            return render(request, 'login.html')


def index(request):
    # 获取当前用户的随机字符串
    # 根据随机字符串获取对应的信息
    if request.session['is_login']:
        return HttpResponse(request.session['username'])
    else:
        return HttpResponse('gun')
views.py

session类型

python manage.py makemigrations

python manage.py migrateDjango默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
 
 
 
b. 使用
 
    def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在则不设置
        del request.session['k1']    #删除单个session

    request.session.clear (request.session.session_key)    #用于注销
 
        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用户session的随机字符串
        request.session.session_key
 
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
 
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
 
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。
数据库session
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
 a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
 
 
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
缓存session
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
 
文件session
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
缓存+数据库session
a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
加密cookie session

session验证码

后续不上

CSRF

原理:第一次访问的时候,获取字符串,post请求的时候,将字符串带上发送过去

 对get请求没有限制,对post请求才有限制

为了避免post请求的时候报403错误,需要再form表单里面加上{% csrf_token %}

 ajax请求的话,需要加上headers:{'X-CSRFtoken':$.cookie('csrftoken')},

或者直接加上全局函数

{#            全局变量,对函数内所有ajax有效#}
            $.ajaxSetup({
                beforeSend:function (xhr,settings) {
{#                    设置请求头#}
                    xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                }


             });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login/" method="post">
        <input type="text" name="user" />
        <input type="password" name="pwd" />
        <input type="checkbox" name="rmb" value="1" />3秒钟免登陆
        <input type="submit" value="提交"/>
        <input id="btn1" type="button" value="按钮1"/>
        <input id="btn2" type="button" value="按钮2"/>
        {%  csrf_token %}
    </form>
    <script src="/static/jquery-1.12.4.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $(function () {
{#            全局变量,对函数内所有ajax有效#}
            $.ajaxSetup({
                beforeSend:function (xhr,settings) {
{#                    设置请求头#}
                    xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                }


             });
            
            $('#btn1').click(function () {
{#                var csrftoken = $.cookie('csrftoken');#}
                $.ajax({
                    url:'/login/',
                    type:'POST',
                    data:{'user':'root','pwd':'123'},
{#                    发送post请求的时候,需要加上才放置csrf阻止,由于上面$.ajaxSetup已经配置,所以不需要单独配置#}
{#                    headers:{'X-CSRFtoken':$.cookie('csrftoken')},#}
                    success:function (data) {
                        console.log(1)
                    }
                });
                 $('#btn2').click(function () {
{#                var csrftoken = $.cookie('csrftoken');#}
                $.ajax({
                    url:'/login/',
                    type:'POST',
                    data:{'user':'root','pwd':'123'},
{#                    发送post请求的时候,需要加上才放置csrf阻止#}
{#                    headers:{'X-CSRFtoken':$.cookie('csrftoken')},#}
                    success:function (data) {
                        console.log(2)
                    }
                })
            })
        });
        })

    </script>
</body>
</html>
login.html
全局:
    settings.py里面的MIDDLEWARE下
  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

局部的例子如下

中间件

中间件拥有的函数(名字不能修改):

class Row1(MiddlewareMixin):
    def process_request(self,request):
        print("row1_process_request")

    def process_response(self,request,response):
        print('row1_process_response')
        return response

 中间件的一般逻辑如下图

Django1.10版本之前,若是遇到有return的process_request情况

Django1.10版本后,若是遇到有return的process_request情

中间件是在settings.py的MIDDLEWARE配置的,配置路径,到类

from django.utils.deprecation import MiddlewareMixin

class Row1(MiddlewareMixin):
    def process_request(self,request):
        print("row1_process_request")

    def process_response(self,request,response):
        print('row1_process_response')
        return response

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print("row2_process_request")

    def process_response(self,request,response):
        print('row2_process_response')
        return response

class Row3(MiddlewareMixin):
    def process_request(self,request):
        print("row3_process_request")

    def process_response(self,request,response):
        print('row3_process_response')
        return response
m1.py

多了process_view

    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        '''
        :param request:
        :param view_func: 访问的时候对应views.py里面的函数
        :param view_func_args: views.py里面的函数的参数
        :param view_func_kwargs: views.py里面的函数的参数(字典)
        :return:
        '''
        print('row1_process_view')

多了process_exception,若views.py里面对应的函数出现异常,会一个个中间件寻找能处理的异常函数,若没有,则页面报错,若存在,则返回对应的信息给前端

    def process_exception(self,request,exception):
        '''
        view里面对应的函数出现异常的时候执行
        :param exception: 对应异常
        :return:
        '''
        if isinstance(exception,ValueError):
            # 假设login函数出现异常,又没有处理,只需要这里返回信息,页面不会显示返回的信息
            print('row3_process_exception')
            return HttpResponse('出问题了')
from django.utils.deprecation import MiddlewareMixin

class Row1(MiddlewareMixin):
    def process_request(self,request):
        print("row1_process_request")

    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        '''
        :param request:
        :param view_func: 访问的时候对应views.py里面的函数
        :param view_func_args: views.py里面的函数的参数
        :param view_func_kwargs: views.py里面的函数的参数(字典)
        :return:
        '''
        print('row1_process_view')

    def process_response(self,request,response):
        print('row1_process_response')
        return response
from django.shortcuts import HttpResponse

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print("row2_process_request")
        # return HttpResponse('走')
    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('row2_process_view')

    def process_response(self,request,response):
        print('row2_process_response')
        return response

class Row3(MiddlewareMixin):
    def process_request(self,request):
        print("row3_process_request")
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('row3_process_view')

    def process_response(self,request,response):
        print('row3_process_response')
        return response

    def process_exception(self,request,exception):
        '''
        view里面对应的函数出现异常的时候执行
        :param exception: 对应异常
        :return:
        '''
        if isinstance(exception,ValueError):
            # 假设login函数出现异常,又没有处理,只需要这里返回信息,页面不会显示返回的信息
            print('row3_process_exception')
            return HttpResponse('出问题了')
m1.py
from django.shortcuts import render,redirect,HttpResponse

# Create your views here.
def login(request):
    int('dsd')
    return render(request,'login.html')
views.py

 缓存

 配置:

# 此为开始调试用,实际内部不做任何操作
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                },
                'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                'VERSION': 1,                                                 # 缓存key的版本(默认1)
                'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
            }
        }


    # 自定义key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.

        Constructs the key used by all other methods. By default it prepends
        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return '%s:%s:%s' % (key_prefix, version, key)

    def get_key_func(key_func):
        """
        Function to decide which key function to use.

        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func
1.开发调试
# 此缓存将内容保存至内存的变量中
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

    # 注:其他配置同开发调试版本
2.内存
# 此缓存将内容保存至文件
    # 配置:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': '/var/tmp/django_cache',
            }
        }
    # 注:其他配置同开发调试版本
3.文件
# 此缓存将内容保存至数据库

    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                'LOCATION': 'my_cache_table', # 数据库表
            }
        }

    # 注:执行创建表命令 python manage.py createcachetable
4.数据库
# 此缓存使用python-memcached模块连接memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }
5.Memcache缓存(python-memcached模块)
# 此缓存使用pylibmc模块连接memcache
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }
6.Memcache缓存(pylibmc模块)
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}
            # "PASSWORD": "密码",
        }
    }
}
7.Redis缓存(依赖:pip3 install django-redis)

应用

使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

    MIDDLEWARE = [

    #这个中间件只有一个process_response,进来的时候不需要经过它
        'django.middleware.cache.UpdateCacheMiddleware',
        # 其他中间件...

    #这里只有process_view,出去的时候不需要经过
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]

    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""
全局视图
# 单视图,整个页面的缓存,设置为10秒,这里的优先级比默认的高
from django.views.decorators.cache import cache_page
@cache_page(10)
def cache(request):
    import time
    ctime = time.time()
    return render(request,'cache.html',{'ctime':ctime})
单视图缓存

局部缓存在html写,需要导入

{% load cache %}
在需要缓存的地方上写,单位是秒,这里缓存10秒
{% cache 10 c1 %}
<h1>{{ ctime }}</h1>
{% endcache %}
{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{ ctime }}</h1>
    <h1>{{ ctime }}</h1>
    {% cache 10 c1 %}
        <h1>{{ ctime }}</h1>
    {% endcache %}

</body>
</html>
局部缓存.html

信号

(可以做日志)

Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发
Django内置信号

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

使用:

from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception

from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate

from django.test.signals import setting_changed
from django.test.signals import template_rendered

from django.db.backends.signals import connection_created


def callback(sender, **kwargs):
    print("xxoo_callback")
    print(sender,kwargs)

# xxoo.connect(callback)
# xxoo指上述导入的内容
# 例如:
pre_init.connect(callback)
sg.py

init.py导入sy.py

from app01 import models
def sigin(request):
    obj = models.UserInfo(username='root')
    print('end')
    obj.save()
    obj = models.UserInfo(username='root')
    obj.save()

    obj = models.UserInfo(username='root')
    obj.save()
views.py

自定义信号

1.定义信号

2.触发信号

3.信号中注册函数

sg.py加上这个

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

注册对应函数

def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
 
pizza_done.connect(callback)

def sigin(request):
    from sg import pizza_done
    # sender随意些,后面的传递参数内容
    pizza_done.send(sender='sddsfs', toppings=123, size=456)
    return HttpResponse('ok')
views.py

form表单验证

参考:http://www.cnblogs.com/wupeiqi/articles/6144178.html

1.验证用户请求
2.生成HTML标签,保留上一次填写的记录
{{obj.user}}      

3.显示错误信息{{ obj.errors.user.0 }}

<p>{{ obj.user }}{{ obj.errors.user.0 }}</p>

 4.从数据库获取信息好返回到前端

rom django import forms
from django.forms import fields
class FM(forms.Form):
    # 这里的变量与前端form里面的name一致才能获取对应的值
    # user = forms.CharField()
    # 可以自定义对应错误信息
    user = forms.CharField(error_messages={'required':'用户名不能为空。'})

    #  pwd = forms.CharField()
    pwd = forms.CharField(
        max_length=12,
        min_length=6,
        error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'}
    )
    # 单选下拉
    city1 = fields.ChoiceField(
        choices=[(0,'上海'),(1,'广州'),(2,'东莞')]
    )
    # 多选下拉
    city2 = fields.MultipleChoiceField(
        choices=[(0, '上海'), (1, '广州'), (2, '东莞')]
    )

    # email = forms.EmailField()
    email = forms.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})

def fm(request):
    if request.method == 'GET':

        # 从数据库中获取到数据
        dic = {
            'user':'root',
            'pwd':'123123',
            'email':'sada@111',
            'city1':1,
            'city2':[1,2]
        }

        # obj = FM()
        # 将获取到的数据传递到类FM
        obj = FM(initial=dic)
        return render(request,'fm.html',{'obj':obj})
    elif request.method == 'POST':
        # 获取用户所有数据
        # 每条数据请求的验证
        # 成功后,获取所有的正确的信息
        # 如果失败,显示错误信息
        # 这次请求是post里面的数据,所以传入request.POST
        obj = FM(request.POST)
        r1= obj.is_valid()
        print(r1)
        if r1:
            print(obj.cleaned_data)

        else:
            # obj.errors是字典
            print(obj.errors)
            print(obj.errors.as_json())
            print(obj.errors['user'])
            print(obj.errors['user'][0])

            return render(request,'fm.html',{'obj':obj})

        return redirect('/fm/')
eg

 先导入对应forms,然后生成类

from django import forms(不建议使用)
from django.forms import fields(建议使用这个)
 
from django import forms
class FM(forms.Form):
    # 这里的变量与前端form里面的name一致才能获取对应的值
    # user = forms.CharField()
    # 可以自定义对应错误信息
    user = forms.CharField(error_messages={'required':'用户名不能为空。'})

    #  pwd = forms.CharField()
    pwd = forms.CharField(
        max_length=12,
        min_length=6,
        error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'}
    )

    # email = forms.EmailField()
    email = forms.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})

def fm(request):
    if request.method == 'GET':
        obj = FM()
        return render(request,'fm.html',{'obj':obj})
    elif request.method == 'POST':
        # 获取用户所有数据
        # 每条数据请求的验证
        # 成功后,获取所有的正确的信息
        # 如果失败,显示错误信息
        # 这次请求是post里面的数据,所以传入request.POST
        obj = FM(request.POST)
        r1= obj.is_valid()
        print(r1)
        if r1:
            print(obj.cleaned_data)
            # 这样就能创建用户对象了
            models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # obj.errors是字典
            print(obj.errors)
            print(obj.errors.as_json())
            print(obj.errors['user'])
            print(obj.errors['user'][0])

            return render(request,'fm.html',{'obj':obj})

        return redirect('/fm/')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="post">
        {% csrf_token %}
{#        能自动生成标签,并且在新浏览器里面有特定的错误功能 ,建议使用这个,定制性比较好#}
        {{ obj.user }}
        <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
        <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
        <p><input type="submit" value="确定" />

{#            *********************************#}
{#        {{ obj.as_ul }}#}

{#        ****************table需要加上table标签*****************#}
{#        <table>#}
{#            {{ obj.as_table }}#}
{#         </table>#}
{##}
{#        *********************************#}
{#        {{ obj.as_p }}#}

    </form>

</body>
</html>
fm.html
from django.shortcuts import render,redirect,HttpResponse

# Create your views here.
def login(request):
    int('dsd')
    return render(request,'login.html')
# 单视图,整个页面的缓存,设置为10秒,这里的优先级比默认的高
# from django.views.decorators.cache import cache_page
# @cache_page(10)
def cache(request):
    import time
    ctime = time.time()
    return render(request,'cache.html',{'ctime':ctime})

from app01 import models
def sigin(request):
    from sg import pizza_done
    # sender随意些,后面的传递参数内容
    pizza_done.send(sender='sddsfs', toppings=123, size=456)



    obj = models.UserInfo(username='root')
    print('end')
    obj.save()
    obj = models.UserInfo(username='root')
    obj.save()

    obj = models.UserInfo(username='root')
    obj.save()
    return  HttpResponse('ok')



from django import forms
# 多行文本导入,插件
from django.forms import widgets
# 建议将forms改为fields
from django.forms import fields
class FM(forms.Form):
    # 这里的变量与前端form里面的name一致才能获取对应的值
    # user = forms.CharField()
    # 可以自定义对应错误信息
    # 字段本身只做验证
    user = fields.CharField(error_messages={'required':'用户名不能为空。'})

    #  pwd = forms.CharField()
    pwd = fields.CharField(
        max_length=12,
        min_length=6,
        error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'},
        # 密码框
        # widget = widgets.PasswordInput
        # 如果想定制样式
        widget = widgets.PasswordInput(attrs={'class':'c2'})
    )

    # email = forms.EmailField()
    email = fields.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})
    text1 = fields.CharField(
        # attrs={'class':'c1'}定义样式为c1
        widget = widgets.Textarea(attrs={'class':'c1'})
    )

def fm(request):
    if request.method == 'GET':
        obj = FM()
        return render(request,'fm.html',{'obj':obj})
    elif request.method == 'POST':
        # 获取用户所有数据
        # 每条数据请求的验证
        # 成功后,获取所有的正确的信息
        # 如果失败,显示错误信息
        # 这次请求是post里面的数据,所以传入request.POST
        obj = FM(request.POST)
        r1= obj.is_valid()
        print(r1)
        if r1:
            print(obj.cleaned_data)
            # 这样就能创建用户对象了
            models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # obj.errors是字典
            print(obj.errors)
            print(obj.errors.as_json())
            print(obj.errors['user'])
            print(obj.errors['user'][0])

            return render(request,'fm.html',{'obj':obj})

        return redirect('/fm/')
优化的views.py—1

初始化操作:

  

def fm(request):
    if request.method == 'GET':

        # 从数据库中获取到数据
        dic = {
            'user':'root',
            'pwd':'123123',
            'email':'sada@111',
            'city1':1,
            'city2':[1,2]
        }

        # obj = FM()
        # 将获取到的数据传递到类FM
        obj = FM(initial=dic)
        return render(request,'fm.html',{'obj':obj})

 modelform(耦合性太强,小的程序才用)

参考:https://www.cnblogs.com/wupeiqi/articles/6229414.html

# modelform方式
class UserInfoModelForm(forms.ModelForm):

    class Meta:
        # 这里指定字段对应的表
        model  =models.UserInfo
        # __all__代表多有的字段
        fields = '__all__'

        # 只显示的字段
        # fields = ['username','email']
        # 排除字段,其他的显示
        exclude = ['email']
# # modelform方式
class UserInfoModelForm(forms.ModelForm):

    class Meta:
        # 这里指定字段对应的表
        model  =models.UserInfo
        # __all__代表多有的字段
        fields = '__all__'

        # 只显示的字段
        # fields = ['username','email']
        # 排除字段,其他的显示
        # exclude = ['email']
        # 显示标签更名
        labels = {
            'username':'用户名',
            'email':'邮箱'
        }
        #
        help_texts = {
            'username':'帮助信息'
        }
        # 将原来的CharField改为为Textarea
        widgets = {
            'username':Fwidgets.Textarea(attrs={'class':'c1'})
        }
        error_messages = {
            '__all__':'所有字段共同的错误',
            # email的错误信息
            'email':{
                'required':'邮箱不能为空',
                'invalid':'邮箱格式错误'

            }
        }
        # 更改格式,
        field_classes = {
            # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
            'email': Ffields.URLField
        }
views.py

1.可以生产HTML标签:class Meta的参数

2.页面显示带默认值,就需增加instance参数如:mf = xxxModelForm(instance = ModelObj)

3.额外的标签:is_rmb = Ffields.CharField( widget=Fwidgets.CheckboxInput() )

4.各种验证 is_valid() - > 各种钩子

5.mf.save(),可以拆开

instance = obj.save(False)
instance.save()
obj.save_m2m()
from django.shortcuts import render
from django import forms
from django.forms import fields
from django.forms import fields as Ffields
from app01 import models
# Create your views here.

# 避免跟modelform的属性冲突,更名为Fwidgets
from django.forms import widgets as Fwidgets
# # modelform方式
class UserInfoModelForm(forms.ModelForm):

    # 自定义字段,跟保存在数据库上没关系,例如一个月内免登陆的CheckBox
    is_rmb = Ffields.CharField(     widget=Fwidgets.CheckboxInput() )

    class Meta:
        # 这里指定字段对应的表
        model  =models.UserInfo
        # __all__代表多有的字段
        fields = '__all__'

        # 只显示的字段
        # fields = ['username','email']
        # 排除字段,其他的显示
        # exclude = ['email']
        # 显示标签更名
        labels = {
            'username':'用户名',
            'email':'邮箱'
        }
        #
        help_texts = {
            'username':'帮助信息'
        }
        # 将原来的CharField改为为Textarea
        widgets = {
            'username':Fwidgets.Textarea(attrs={'class':'c1'})
        }
        error_messages = {
            '__all__':'所有字段共同的错误',
            # email的错误信息
            'email':{
                'required':'邮箱不能为空',
                'invalid':'邮箱格式错误'

            }
        }
        # 更改格式,
        # field_classes = {
        #     # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
        #     'email': Ffields.URLField
        # }

# form方式
class UserInfoForm(forms.Form):
    # 定义字段
    username = fields.CharField(max_length=32,label='用户名')
    email = fields.EmailField(label='邮件')
    # 将数据库的id caption字段作为下拉显示
    user_type = fields.ChoiceField(
        choices = models.UserType.objects.values_list('id','caption'),
        label='类型'
    )
    def __init__(self,*args,**kwargs):
        super(UserInfoForm,self).__init__(*args,**kwargs)
        # 这样子就能更新数据库不需要重启程序就能更新数据
        self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')

def index(request):

    if request.method == 'GET':

        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoModelForm()

        return render(request,'index.html',{'obj':obj})
        # return render(request,'index.html')
    elif request.method == 'POST':
        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoModelForm(request.POST)
        if obj.is_valid():
            # obj.save()
            # 上面一句包含了下面三句代码,只不过默认传入commit=True
            instance = obj.save(False)
            instance.save()
            obj.save_m2m()
        # print(obj.is_valid())
        # print(obj.cleaned_data)
        # print(obj.errors)
        # obj.cleaned_data

        return render(request, 'index.html', {'obj': obj})



def user_list(request):

    li = models.UserInfo.objects.all().select_related('user_type')
    return render(request,'user_list.html',{'li':li})


def user_edit(request,nid):
    # 获取当前id对象的用户信息
    # 显示用户已经存在的数据
    if request.method == "GET":
        user_obj = models.UserInfo.objects.filter(id=nid).first()
        mf = UserInfoModelForm(instance=user_obj)
        return render(request,'user_edit.html',{'mf':mf,'nid':nid})
    elif request.method == 'POST':
        user_obj = models.UserInfo.objects.filter(id=nid).first()
        # instance=user_obj)告诉数据库要更新的是哪个对象
        mf = UserInfoModelForm(request.POST,instance=user_obj)
        if mf.is_valid():
            mf.save()

        else:
            print(mf.errors.as_json())
        return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})
views.py代码变成

form

  UserInfoForm 继承Form,又继承BaseForm(方法所在)

from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models
# Create your views here.
# # modelform方式
# class UserInfoModelForm(forms.ModelForm):
#
#     class Meta:
#         # 这里指定字段对应的表
#         model  =models.UserInfo
#         # __all__代表多有的字段
#         fields = '__all__'
#
#         # 只显示的字段
#         # fields = ['username','email']
#         # 排除字段,其他的显示
#         exclude = ['email']


# form方式
class UserInfoForm(forms.Form):
    # 定义字段
    username = fields.CharField(max_length=32,label='用户名')
    email = fields.EmailField(label='邮件')
    # 将数据库的id caption字段作为下拉显示
    user_type = fields.ChoiceField(
        choices = models.UserType.objects.values_list('id','caption'),
        label='类型'
    )
    def __init__(self,*args,**kwargs):
        super(UserInfoForm,self).__init__(*args,**kwargs)
        # 这样子就能更新数据库不需要重启程序就能更新数据
        self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')

def index(request):

    if request.method == 'GET':

        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoForm()

        return render(request,'index.html',{'obj':obj})
        # return render(request,'index.html')
    elif request.method == 'POST':
        # 创建对象,会在前段自动生成对应的标签
        obj = UserInfoForm(request.POST)
        obj.is_valid()
            # obj.cleaned_data

        return render(request, 'index.html', {'obj': obj})
views.py

 

select_related()

使用外键.出数据的情况,Django会导致请求数据库过多,例如,下面一个循环,就进行了11次请求,效率不高

但是,如果后面加上select_related(),就会将表关联的数据一次拿出来了。当然,这样有所有的数据,所以会导致请求的数据过多,因此,可以增加对应的参数select_related('ut')

prefetch_related

  users = models.User.objects.filter(id__gt=30).prefetch_related('ut') 会执行两次SQL请求

  # select * from users; where id > 30;

  # 获取上一步骤中所有的ut_id = [1,2]

  # select * from user_type where id in[1,2],所以下面就能直接从内存获取数据,而不需要再执行SQL请求

  for row in users:

    print(row.user,row.pwd,row.ut_id)

    print(row.ut.name)

obj.full_clean()会对内容进行验证,若错误,则会抛出异常

 步骤:每个字段的正则验证

    clean钩子  

可以利用继续的clean()方法,自定义错误

kindEditor(视频132)

参考:http://www.cnblogs.com/wupeiqi/articles/6307554.html 

官网:http://kindeditor.net/demo.php

初始化参数:http://kindeditor.net/docs/option.html

组合查询

开始的做法

from django.shortcuts import render
from app01 import models

# Create your views here.


def article(request,*args,**kwargs):
    # print(request.path_info)
    # from django.urls import reverse
    # # 反转获取url
    # url = reverse('article',kwargs=kwargs)
    # print(url)
    print(args)
    condition = {}
    for k,v in kwargs.items():
        kwargs[k] = int(v)
        # print(type(k))
        if v == '0':
            # print('什么都不做')
            pass
        else:
            condition[k] = v

    # {'article_type_id': '1', 'category_id': '0'}
    print(kwargs)
    article_type_list = models.ArticleType.objects.all()
    category_list = models.Category.objects.all()

    result = models.Article.objects.filter(**condition)
    return render(request,
                  'article.html',
                  {'result':result,
                   'article_type_list':article_type_list,
                   'category_list':category_list,
                   'arg_dict':kwargs

                   })
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .condition a{
            display: inline-block;
            padding: 3px 5px;
            border: 1px solid #DDDDDD;
            margin: 5px;
        }
        .condition a.active{
            background-color: green;
        }
    </style>
</head>
<body>
    <h1>过滤条件</h1>
    <div class="condition">
        <div>
            {% if arg_dict.article_type_id == 0 %}
                 <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>
             {% else %}
            <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>
            {% endif %}
            {% for row in article_type_list %}
                {% if row.id == arg_dict.article_type_id %}
                    <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
                {% else %}
                    <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
                {% endif %}
            {% endfor %}
        </div>

          <div>
              {% if arg_dict.category_id == 0 %}
                <a class="active" href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>
                  {% else %}
                <a href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>
                {% endif %}
            {% for row in category_list %}
                {% if row.id == arg_dict.category_id  %}
                    <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                {% else %}
                    <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                {% endif %}
            {% endfor %}
        </div>
    </div>
    <h1>查询结果</h1>
    <ul>
        {% for row in result %}
                <li>{{ row.id }}-{{ row.title }}</li>
        {% endfor %}
    </ul>
</body>
</html>
article.html

优化:

在app01建立新目录templatetags,建立任意.py文件,然后建立模板

from django import template

register = template.Library()

# 注册成模板
@register.simple_tag
def filter_all():

    return '....'

HTML文件头部写  {% load py文件名 %} 如:{% load filter %}

输出:{% 函数名 %}  {% filter_all %}

from django import template
from django.utils.safestring import mark_safe
register = template.Library()

# 注册成模板
@register.simple_tag
def filter_all(arg_dict,k):
    '''
    因为内容以来于arg_dict,所以传递入参数
            {% if arg_dict.article_type_id == 0 %}
                 <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>
             {% else %}
                <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>
            {% endif %}
    :return:
    '''
    if k == 'article_type_id':
        n1 =arg_dict['article_type_id']
        n2=arg_dict['category_id']
        if n1 ==0:
            ret = '<a class="active" href="/article-0-%s/">全部</a>' % n2
        else:
            ret = '<a href="/article-0-%s/">全部</a>' % n2

    else:
        n1 = arg_dict['category_id']
        n2 = arg_dict['article_type_id']
        if n1 == 0:
            ret = '<a class="active" href="/article-%s-0/">全部</a>' % n2
        else:
            ret = '<a  href="/article-%s-0/">全部</a>' % n2




    # if arg_dict['article_type_id'] == 0:
    #     ret='<a class="active" href="/article-0-%s/">全部</a>'%(arg_dict['category_id'])
    # else:
    #     ret='<a  href="/article-0-%s/">全部</a>'%(arg_dict['category_id'])

    return mark_safe(ret)
@register.simple_tag
def filter_article_type(arg_dict,article_type_list):
    '''
    {% for row in article_type_list %}
        {% if row.id == arg_dict.article_type_id %}
            <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
        {% else %}
            <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
        {% endif %}
    {% endfor %}
    :return:
    '''
    ret = []
    for row in article_type_list:
        if row.id == arg_dict['article_type_id']:
            temp = '<a class="active" href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
        else:
            temp = '<a  href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)

        ret.append(temp)

    return mark_safe(''.join(ret))

# @register.simple_tag
# def filter_article_type(arg_dict,article_type_list):
#     '''
#     {% for row in article_type_list %}
#         {% if row.id == arg_dict.article_type_id %}
#             <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
#         {% else %}
#             <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
#         {% endif %}
#     {% endfor %}
#     :return:
#     '''
#     ret = []
#     for row in article_type_list:
#         if row.id == arg_dict['article_type_id']:
#             temp = '<a class="active" href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
#         else:
#             temp = '<a  href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
#
#         ret.append(temp)
#
#     return mark_safe(''.join(ret))
filter.py
from django.shortcuts import render
from app01 import models

# Create your views here.


def article(request,*args,**kwargs):
    # print(request.path_info)
    # from django.urls import reverse
    # # 反转获取url
    # url = reverse('article',kwargs=kwargs)
    # print(url)
    print(args)
    condition = {}
    for k,v in kwargs.items():
        kwargs[k] = int(v)
        # print(type(k))
        if v == '0':
            # print('什么都不做')
            pass
        else:
            condition[k] = v

    # {'article_type_id': '1', 'category_id': '0'}
    print(kwargs)
    article_type_list = models.ArticleType.objects.all()
    category_list = models.Category.objects.all()

    result = models.Article.objects.filter(**condition)
    return render(request,
                  'article.html',
                  {'result':result,
                   'article_type_list':article_type_list,
                   'category_list':category_list,
                   'arg_dict':kwargs

                   })
views.py
{% load filter %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .condition a{
            display: inline-block;
            padding: 3px 5px;
            border: 1px solid #DDDDDD;
            margin: 5px;
        }
        .condition a.active{
            background-color: green;
        }
    </style>
</head>
<body>
    <h1>过滤条件</h1>
    <div class="condition">
        <div>
            {% filter_all arg_dict 'article_type_id' %}
            {% filter_article_type arg_dict article_type_list %}
{#            {% if arg_dict.article_type_id == 0 %}#}
{#                 <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>#}
{#             {% else %}#}
{#            <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>#}
{#            {% endif %}#}
{#            {% for row in article_type_list %}#}
{#                {% if row.id == arg_dict.article_type_id %}#}
{#                    <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>#}
{#                {% else %}#}
{#                    <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>#}
{#                {% endif %}#}
{#            {% endfor %}#}
        </div>

          <div>
          {% filter_all arg_dict 'category_id' %}

{#              {% if arg_dict.category_id == 0 %}#}
{#                <a class="active" href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>#}
{#                  {% else %}#}
{#                <a href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>#}
{#                {% endif %}#}
            {% for row in category_list %}
                {% if row.id == arg_dict.category_id  %}
                    <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                {% else %}
                    <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                {% endif %}
            {% endfor %}
        </div>
    </div>
    <h1>查询结果</h1>
    <ul>
        {% for row in result %}
                <li>{{ row.id }}-{{ row.title }}</li>
        {% endfor %}
    </ul>
</body>
</html>
article.html

JSONP

是一种请求方式

因为浏览器的同源策略(阻止Ajax请求,无法阻止<scritp src...>请求)

巧妙:

  创建script标签

  src=远程地址

  返回的数据必须是js格式的

只能发GET请求

后续补充

注意地方:

1、写url的时候,建议增加结尾符合$,否则business_add地址永远无法执行

原文地址:https://www.cnblogs.com/cheng662540/p/9351284.html