Django基础

一、简介

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的软件设计模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。

Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下:

模型(Model),即数据存取层

处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。

模板(Template),即表现层

处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。

视图(View),即业务逻辑层

存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。

基本目录结构:

mysite                   #django工程
    - mysite             # 整个站点配置目录
        - __init__.py
        - settings.py       # 配置文件
        - urls.py           # 路由关系
        - wsgi.py           # 遵循WSIG规范,生产一般采用uwsgi + nginx
    - manage.py     # Django管理程序
                      
二、安装配置django以及基本命令使用

1、安装django

#windows
pip install django
python -m pip install django

#linux或者mac
pip3 install django
pip install django=1.9.5

#检查django是否安装成功

运行python终端
>>> import django
>>> django.VERSION

2、创建django工程以及app

pycharm中创建:file-->New Project-->Django-->create

使用命令创建

#创建工程
django-admin.py startproject projectname

#创建app
python manage.py startapp appname

tips:django中的工程和app概念,django相当于一个大项目,而其中的小系统如监控、资产管理属于这个项目的一部分我们称之为app。

app目录结构

app :
    migrations     #数据库修改表结构记录
    admin.py          #Django提供的后台管理
    apps.py           #当前app配置文件
    models.py         #Django中的ORM,写指定的类  通过命令可以创建数据库结构
    tests.py          #项目的单元测试
    views.py          #MTV中的视图,用于写业务逻辑

 3、配置django

模板配置:django工程-->相应工程名-->settings.py-->TEMPLATES(默认配置好的)

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',
            ],
        },
    },
]

静态目录(图片、css)配置:django工程-->相应工程名-->settings.py-->STATICFILES_DIRS(需要自己手动添加,目录使用逗号隔开)

STATICFILES_DIRS = (
   os.path.join(BASE_DIR, "static"),
)

 tips:若访问某个连接出现forbbiden,很有可能是有CSRF原因,可以在配置中注释

settings.py

 4、其他django常用命令

#创建django命令
django-admin.py startproject project-name
#创建django的app
python manage.py startapp app-name
或 django-admin.py startapp app-name
#同步数据库
python manage.py syncdb
#注意:Django 1.7.1及以上的版本需要用以下命令
python manage.py makemigrations
python manage.py migrate
#命令行调试模式
python manage.py runserver 8001
python manage.py runserver 0.0.0.0:8000
#清除数据库
python manage.py flush
#创建超级管理员
python manage.py createsuperuser
按照提示输入
#修改管理员密码
python manage.py changepassword username(需要修改的用户名)
#导入和导出数据
python manage.py dumpdata appname > appname.json
python manage.py loaddata appname.json
#进入数据库
python manage.py dbshell
三、开始你的站点

 1、配置路由(工程目录中的urls.py)

from django.conf.urls import url
from django.contrib import admin
from cmdb import views
#从app中导入views视图
urlpatterns = [
    url(r'^admin/', admin.site.urls),
     #当用户访问http://127.0.0.1:8000/admin/时候使用admin.site.urls处理
    url(r'^$',views.index),
    #当用户访问http://127.0.0.1:8000,采用views下面的index函数处理,^表示开头,$表示结尾
]

2、使用views处理用户请求(app下面的views.py)

from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def index(request):
  #request中包含了用户所有的请求数据,通过该参数可以获取很多请求信息比如:
     # request.method   GET / POST  #获取用户请求的方法
     # request.GET.get('key')    #获取请求发来的而数据,参数为数据key
     # request.POST.get('key')
return render(request,'index.html')#使用模板处理、响应用户请求,参数至少是两个,第一个固定为request,第二个为templates下的模板文件

#return HttpResponse("<p>this is wd </p>") #使用HttpResponse响应用户请求,参数为字符串

#return redirect("http://www.baidu.com") #将用户请求重定向到百度,若本地跳转只能写目录,比如'/login'

3、在templates目录中创建模板文件index.html,若模板文件中需要引入css或者images等内容,路径需要加上static,如

<link rel="stylesheet" href="/static/css/core/main.css">

4、运行django程序,访问http://127.0.0.1:8000你的站点就会呈现

四、视图(views)介绍

django中的视图用于处理业务逻辑,常用的定义试图方法有两种:FBV(fuction base  view)、CBV(class base view)

1、FBV

views.py使用函数作为逻辑处理

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

2、CBV

views.py使用面向对象的方式定义

class login(View):#需要继承View类
     def dispath(self, request, *args, **kwargs):
          print("before do something")
          result = super(login, self).dispath(request, *args, **kwargs)#执行父类方法,使得重写子类方法不影响其他操作
          print("after do something")
          return result #需要将结果返回

     def get(self, request):#处理get方法的请求
          print(request.method)
          return render(request, "index.html")

     def post(self, request):#处理post方法的请求
          print(request.method)
          return render(request, "index.html")

使用cbv进行处理时候最,需要在urls.py中使用as_view()方法

url(r'^$', views.login.as_view())
五、模板语言(template)

若我们想让前端和后台进行数据交互、传递,那我需要了解django中的模板引起,下面简单介绍常用的模板语言。

1、获取单个数据,后台视图传递数据:{{ key }}

视图函数:

def person(request):
    if request.method=="GET":
        user_dict={'name':'wd','age':22}
        return render(request,'person.html',user_dict)#通过模板传递第三个参数,向html页面传递数据

模板文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{{ name }}</h1>
<h1>{{ age }}</h1>
</body>
</html>

2、使用for循环

 语法:

{% for item in item_list %}  
<a>{{ item }}</a>  
{% endfor %}

循环字典、列表,生成多行数据:

三种循环方式

<html>
     <body>
          <!-- 列表循环 -->
          {% for i in k1 % }
               <h1>{{ i }}</h1>
          {% endfor % }

          <!-- 字典循环 -->
          {% for k in k2.keys % }
               <h1>{{ k }}</h1>
          {% endfor % }
          
          {% for v in k2.values % }
               <h1>{{ v }}</h1>
          {% endfor % }
          
          {% for k,v in k2.items % }
               <h1>{{ k }}-{{ v }}</h1>
          {% endfor % }
     </body>
</html>

for循环参数介绍:

{{ forloop.counter }} #计数器,循环一次增加1,可以用于获取行数,从1开始

{{ forloop.counter0 }} #计数器,循环一次增加1,可以用于获取行数,从0开始

{{ forloop.revcounter }} #计数器,循环一次增加1,倒叙,1最后

{{ forloop.revcounter0 }} #计数器,循环一次增加1,倒叙,0最后

{{ forloop.counter.first }}  #是否是第一个循环,返回True 或者False

{{ forloop.counter.last }}  #是否是最后一个循环,返回True 或者False

{{ forloop.parentloop }}  #拿到父循环内容

for示例:

#视图函数
def person(request):
    if request.method=="GET":
        USER_INFO = {
            '1': {'name': 'jack', 'age': '22'},
            '2': {'name': 'wd', 'age': '21'},
            '3': {'name': 'rose', 'age': '18'},
        }
        return render(request,'person.html',{'user_info':USER_INFO})

#html模板
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% for row in user_info.values %}
    <p>
        <a>{{ row.name }}</a>
        <a>{{ row.age }}</a>
    </p>
{% endfor %}
</body>
</html>

3、判断

{% if ordered_warranty %}  {% else %} {% endif %}

 4、模版继承(extends)

当html模版中都使用了重复的html代码,我们可以使用模版来代替他们,然后让子模版继承它,但是需要注意的是,一个html只能继承一个模版

母模版:
{% block name %} {% endblock %}

使用:
先声明:
{% extends 'html模版' %}
{% block name %}
自己定义的内容 {% endblock %}

示例:

master.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title  %}{% endblock %}</title>
    <link href="/static/common.css" type="text/css">
    {% block css %}{% endblock %}
</head>
<body>
<div class="pg-header"></div>
<div class="pg-menue"></div>
<div class="pg-context"></div>
{% block context  %}{% endblock %}
<script src="/static/jquery.js"></script>
{% block js %}{% endblock %}
</body>
</html>

继承主模版:child1.html

{% extends 'master.html' %}
{% block title %}监控平台{% endblock %}
{% block context %}
<a>zabbix</a>
<a>nagios</a>
{% endblock %}

5、模版导入(include)

 结合模版继承,一个相对完成的模版文件如下:

item.html

<input type="text">
<input type="text">
<input type="text">

 child2.html

{% extends "master.html" %}  # 继承母版

{% block title %}监控平台{% endblock %}  # 替换标题

{% block css %}  # 导入子版专用CSS文件
    <link rel="stylesheet" href="/static/commons.css">
{% endblock %}

{% block content %}  # 替换内容
    {% include "item.html" %}  # 导入其他共用html模板文件
    <ul>
        {% for row in item %} #循环
            <li>{{ row }}</li>
        {% endfor %}
    </ul>
{% endblock %}

{% block js %}  # 导入子版专用JS文件
    <script src="/static/child.js"></script>
{% endblock %}

 6、自定义simple_tag

作用:在模版语言中可对后台传入的数据进行二次加工。

django提供的内置方法:

{{ item.event_start|date:"Y-m-d H:i:s"}}#转换时间为自己想要的格式,“|”代表管道符号
{{ bio|truncatewords:"30" }}#截取前30个字符串
{{ my_list|first|upper }}#转为大写
{{ name|lower }}#转为小写

自定义simple_tag方法:

步骤:

  • 在app目录下创建templatetags(名字固定)目录
  • 创建任意py文件,如myupper.py
  • 编写内容
#!/usr/bin/env python3
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
   
register = template.Library()#register是固定的类名
   
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
   
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)
View Code
  • 在工程settings.py中注册这个app
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'cmdb.apps.CmdbConfig',
    'app01',
]
View Code
  • 在模版中装载自定义simple_tag的python文件,在模版文件的顶部
{% load myupper %}  #如果有{% extends "master.html" %},则在写在其下方
  • 在模版中使用自定义的simple_tag函数
{% 函数名 agr1  agr2 %}
#{% my_simple_time 1 1 1 %},返回3,根据你py文件中定义返回的逻辑返回,my_simple_time中定义了三个参数相加,所有返回3

 7、自定义filter

作用:同simple_tag一样,可以给数据做二次处理

 自定义filter步骤(参考simple_tag):

  • 在app目录下创建templatetags(名字固定)目录
  • 创建任意py文件,如myfilter.py
  • 编写内容(这里使用filter类)
from django import template

register = template.Library()  

@register.filter
def my_filter(v1,v2):  # 最多设置两个参数,想设置多个参数需要当作一个字符串传入,然后自己在处理
    return  v1 + v2
View Code
  • 在工程settings.py中注册这个app
  • 在模板文件中装载该python文件
{% load myfilter %}
  • 使用filter
{{参数1|myfilter:参数2}} #如{{  "name"|myfilter:"wd" }},返回namewd,同样根据你filter定义的返回逻辑返回

8、自定义filter和simple_tag优缺点比较

#simple_tag
     缺点:不能作为if条件
     优点:可以设置任意个参数,参数之间可以多个空格
#filter
      缺点:最多只能设置两个参数,且不能加空格
      优点:在模板中,可以作为if模板语音进行条件判断 ,列如:
      {% if "name"|myfilter:"wd" %}
      {% endif %}
六、路由系统(urls.py)

 在Django的urls中我们可以根据一个URL对应一个函数名或者类来定义路由规则:
1、单一(基本)路由规则:

url(r'^login/$', views.index),

2、基于正则表达式的路由

  • 单个正则表达式
url(r'^detail-(d+).html/$', views.detail)
#单个括号,需要在试图函数detail中增加一个参数来接受正则中匹配的内容
#detail函数定义如下
def detail(request,nid):#增加nid形参,接受url传递的参数
    if request.method=='GET':
        user_info=USER_INFO[nid]
        return render(request,"detail.html",{'user_info':user_info})
  • 多个正则,按顺序接受
url(r'^detail-(d+)-(d+).html/$', views.detail)
#detail函数定义
def detail(request,nid,sid):
    pass
#接受参数时候,按顺序接受,比如url是http://127.0.0.1:8000/detail-2-3.html/,第一个参数为2,第二个参数为3。
  • 命名正则路由(和顺序无关系,接受时候按照key,也就是命名的名字接受)
#url中采用?P<name>方式命名
url(r'^detail-(?P<id1>d+)-(?P<id2>d+).html/$', views.detail),
#函数中使用名字作为行参获取值
def detail(request,id1,id2):
    pass

 3、给路由添加额外参数

除了正则路由可以给视图函数传递参数以外,还可以使用路由中直接添加参数

url(r'^detail/', views.detail, {"nid": 12}),
#同样需要在detail函数中增加nid参数来接受传递的参数

4、使用路由别名(name参数)

 url(r'^index/$', views.index,name='my_index'),
url(r
'^detail-(?P<id1>d+)-(?P<id2>d+).html/$', views.detail,name='my_detail'),
#name只能匹配固定的url,若url含参数,需要自己手动添加参数如:{% url "my_index"  "1" "2" %}

作用:

  • 在模板中引用该名字代表其对应的url,如{% url "my_index" %},加参数使用{% url "my_detail"  "1" "2" %}
  • 在视图函数中使用别名,  reverse('"my_detail', args=(1,2))  ,  模块路径:django.urls.reverse
  • Model中使用获取URL  自定义get_absolute_url() 方法
class NewType(models.Model):
    caption = models.CharField(max_length=16)


    def get_absolute_url(self):
        """
        为每个对象生成一个URL
        应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
        :return:
        """
        # return '/%s/%s' % (self._meta.db_table, self.id)
        #
        from django.urls import reverse
        return reverse('NewType.Detail', kwargs={'nid': self.id})
示例

5、url的路由分发

作用:当我们项目中的app有多个时候,将路由都配置在工程的urls.py可能相对繁琐,所以django为了带了目录转发的功能

1、配置工程中的urls.py

#工程的urls.py配置

#导入include
from django.conf.urls import url,include

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^cmdb/',include('cmdb.urls'))#匹配到以cmdb的都转发到cmdb目录下的urls.py中
]

2、在cmdb下新建urls.py,配置目的url

from django.conf.urls import url,include
from django.contrib import admin
#导入cmdb下的view函数
from . import views
urlpatterns = [
    url(r'^index/',views.index),
    url(r'^detail/',views.detail),

]

6、命名空间

 使用namespacse参数给include命名,可以后续反向解析url。

1.工程下面的urls.py

from django.contrib import admin
from cmdb import views
from django.conf.urls import url,include
urlpatterns = [
    url(r'^app01/',include('app01.urls',namespace='myapp01')),
]

2.app01下面的urls.py

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

3.views.py中使用reverse反向解析

def index(request):
    v=reverse('myapp01:myindex')
    print(v)      #输出/app01/index/
    print(request.resolver_match)
    return HttpResponse('ok')


#在模版中解析改地址
{% url 'myapp01:myindex' %}


#带参数的url反解析
v = reverse('myapp01:myindex', kwargs={'page':11})
{% url 'myapp01 :myindex' page=12 %}
七、数据模型(modles)

 django中的数据模型采用的是ORM(Object Relational Mapping)框架,类似sqlachemy。

1.配置数据库、注册app(默认使用sqlite3,无需配置):

使用mysql配置:工程目录-->settings.py

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

python3中无MySQL_db需要在工程目录下的__init__.py文件中配置使用pymysql

import pymysql
pymysql.install_as_MySQLdb() 

注册app:settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'cmdb.apps.CmdbConfig',
    'cmdb',#增加的app名称
]

定义表(类)

from django.db import models

class user(models.Model):  #数据库表名为app_classname,比如现在这个表存在数据库中为cmdb_user
    name=models.CharField(max_length=24)   #字符串,最大长度24
    age=models.IntegerField()  #整数类型

同步数据库:

python3 manage.py makemigrations
python3 manage.py migrate

 2、django中的orm中增删改查

 增(add)

#导入models
from cmdb import models
#方式一,使用create方法        
    models.user.objects.create(name='wd',age=22)
    #参数使用字典方式
    dict= {'name': 'wd', 'age': 22}
    models.User.objects.create(**dict)
#方式二,使用对象方式添加
    obj = models.user(name='wd',age=22)
    obj.save()

删除(delete)

#使用delete方法
models.user.objects.filter(name='wd').delete()

查询(query)

#首先解释下queryset对象:可以认为一个列表其中包含的每个元素都是一个包含一行数据的对象
#获取所有对象,返回queryset对象,
all_object=models.user.objects.all()
#filter 条件过滤类似于sql中的where,加逗号相当于and
models.user.objects.filter(id=2,name='wd')  # id等于2 and name等于wd
models.user.objects.filter(id__gt=2,name='wd')  # id > 2 and name等于wd
models.user.objects.filter(id__lt=3)  # id < 3
models.user.objects.filter(id__gte=1)  # id >= 1
models.user.objects.filter(id__lte=1)  # id <= 1

models.Business.objects.all().values('id','caption')   # QuerySet ,内部元素都是字典
models.user.objects.all().values_list('id','caption')  # QuerySet ,内部元素都是元组
models.user.objects.get(id=3)  # 获取到的一个对象,如果不存在就报错
models.user.objects.filter(name='wd').first()  # 获取到的将是一个对象,获取不到则返回None
models.user.objects.filter(name='wd').last() # 获取最后一个,得到的是一个对象,获取不到则返回None
models.user.objects.all().reverse() # 反转


#查看orm在数据库中使用的sql语句,使用query属性
all_object=models.user.objects.filter(id__gt=2).query
对应sql:

SELECT "cmdb_user"."id", "cmdb_user"."name", "cmdb_user"."age" FROM "cmdb_user" WHERE "cmdb_user"."id" > 2

改(update)

models.user.objects.filter(id__gt=2).update(name='wd',age=22)
#同增加一样使用字典传参
dict = {'name': 'wd', 'age': 22}
models.User.objects.filter(id__gt=2).update(**dict)

 3、获取单表数据的三种方式

#获取对象的方式,内部数据元素是对象
all_obj = models.user.objects.all()#返回queryset类型

#获取某些具体的行,内部数据元素是字典
all_value=models.user.objects.all().values('id','name')#返回queryset类型

#获取某些具体的行,内部数据元素是元祖,取值只能根据索引
all_value=models.user.objects.all().value_list('id','name')#返回queryset类型

 4、django中orm字段类型介绍

    AutoField(Field)
        - int自增列,必须填入参数 primary_key=True

     BigAutoField(AutoField)
        - bigint自增列,必须填入参数 primary_key=True

        注:当model中如果没有自增列,则自动会创建一个列名为id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自动创建一个列名为id的且为自增的整数列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定义自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整数 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整数 0 ~ 32767
    IntegerField(Field)
        - 整数列(有符号的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整数 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

    自定义无符号整数字段

        class UnsignedIntegerField(models.IntegerField):
            def db_type(self, connection):
                return 'integer UNSIGNED'

    BooleanField(Field)
        - 布尔值类型

    NullBooleanField(Field):
        - 可以为空的布尔值

    CharField(Field)
        - 字符类型
        - 必须提供max_length参数, max_length表示字符长度

    TextField(Field)
        - 文本类型

    EmailField(CharField):
        - 字符串类型,Django Admin以及ModelForm中提供验证机制

    IPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制

    GenericIPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
        - 参数:
            protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"

    URLField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证 URL

    SlugField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

    CommaSeparatedIntegerField(CharField)
        - 字符串类型,格式必须为逗号分割的数字

    UUIDField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
        - 参数:
                path,                      文件夹路径
                match=None,                正则匹配
                recursive=False,           递归下面的文件夹
                allow_files=True,          允许文件
                allow_folders=False,       允许文件夹

    FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
            width_field=None,   上传图片的高度保存的数据库字段名(字符串)
            height_field=None   上传图片的宽度保存的数据库字段名(字符串)

    DateTimeField(DateField)
        - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 时间格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

    FloatField(Field)
        - 浮点型

    DecimalField(Field)
        - 10进制小数
        - 参数:
            max_digits,小数总长度
            decimal_places,小数位长度

    BinaryField(Field)
        - 二进制类型

tips: 返回值为字段在数据库中的属性,Django字段默认的值为:
            'AutoField': 'integer AUTO_INCREMENT',
            'BigAutoField': 'bigint AUTO_INCREMENT',
            'BinaryField': 'longblob',
            'BooleanField': 'bool',
            'CharField': 'varchar(%(max_length)s)',
            'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
            'DateField': 'date',
            'DateTimeField': 'datetime',
            'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
            'DurationField': 'bigint',
            'FileField': 'varchar(%(max_length)s)',
            'FilePathField': 'varchar(%(max_length)s)',
            'FloatField': 'double precision',
            'IntegerField': 'integer',
            'BigIntegerField': 'bigint',
            'IPAddressField': 'char(15)',
            'GenericIPAddressField': 'char(39)',
            'NullBooleanField': 'bool',
            'OneToOneField': 'integer',
            'PositiveIntegerField': 'integer UNSIGNED',
            'PositiveSmallIntegerField': 'smallint UNSIGNED',
            'SlugField': 'varchar(%(max_length)s)',
            'SmallIntegerField': 'smallint',
            'TextField': 'longtext',
            'TimeField': 'time',
            'UUIDField': 'char(32)'

5、字段参数介绍

    null                数据库中字段是否可以为空
    db_column           数据库中字段的列名
    db_tablespace
    default             数据库中字段的默认值
    primary_key         数据库中字段是否为主键
    db_index            数据库中字段是否可以建立索引
    unique              数据库中字段是否可以建立唯一索引
    unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
    unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
    unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
    auto_now            创建时,自动生成时间
    auto_now_add        更新时,自动更新为当前时间 ps:需要使用obj.save()的方式才行

#以下是djangoadmin中的特殊字段,在Admin中有特殊的作用 verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf #
= models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator, MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_d+', message='错误了', code='c1'), RegexValidator(regex='root_112233d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )

 6、外键操作

 1、一对多

定义一对多表结构:

from django.db import models


class user(models.Model):
    name=models.CharField(max_length=24)
    age=models.IntegerField()
    user_group=models.ForeignKey('usergroup',to_field='gid')#外键约束,to_field表示关联的字段,生成的字段为user_group_id,不写的话默认和表的主键关联

class usergroup(models.Model):
    gid=models.AutoField(primary_key=True)
    groupname=models.CharField(max_length=20,unique=True)
    ctime=models.DateField(auto_now_add=True)

一对多的增删改查

#增加,先添加外键关联的表,这里先添加组,在添加用户
group_obj=models.usergroup.objects.create(groupname='TEST')
models.user.objects.create(name='wd',age=22,user_group_id='1')


#修改,直接将关联字段设置为null,前提创建表时候制定了外键可以为null user_obj=models.user.objects.filter(name='wd').update(user_group_id='')

#删除 user_obj=models.user.objects.filter(name='wd').delete()

#查询,通过"."和双下划线进行查询 #点方式 v1=models.user.objects.filter(name='wd').first() print(v1.name,v1.age,v1.user_group,sep="|")#正向通过user表查usergroup表,使用. print(v1.user_group.groupname,v1.user_group.ctime)#正向通过user表查usergroup表,使用. #双下划线字段查询 v2=models.user.objects.filter(name='wd').values('name','age','user_group__groupname')#双下划线查询 for row in v2: print(row['name'],row['age'],row['user_group__groupname'],sep='||')

 2、多对多

定义多对多的两种方式:

##########第一种使用传统外键方式关联(自己定义关系)######
class Host(models.Model):
    hid=models.AutoField(primary_key=True)
    hostname=models.CharField(max_length=20)
    ip=models.GenericIPAddressField()

class HostGroup(models.Model):
    gid=models.AutoField(primary_key=True)
    groupname=models.CharField(max_length=22)
#自己定义第三张表,可以随意添加字段
class HostToGroup(models.Model):
    hobj=models.ForeignKey(to='Host',to_field="hid")#生成的数据库表字段为hobj_id
    gobj=models.ForeignKey(to='HostGroup',to_field="gid")#生成的数据库表字段为gobj_id

##########第二种使用django自带的方式创建########
class Host(models.Model):
    hid=models.AutoField(primary_key=True)
    hostname=models.CharField(max_length=20)
    ip=models.GenericIPAddressField()

class HostGroup(models.Model):
    gid=models.AutoField(primary_key=True)
    groupname=models.CharField(max_length=22)
    hobj=models.ManyToManyField('Host')
    #使用django自带字段创建第三张表,自动关联主键,数据库表名为cmdb_hostgroup_hobj,这种方式不能直接操作第三张表,可以间接操作

django中的orm多对多的增删改查

#增加(add方法)
obj=HostGroup.objects.get(id=1)#获取到主机组对象
obj.hobj.add(2)#添加Host表中id=2的主机
obj.hobj.add(2,3,4)#多个添加
obj.hobj.add(*[1,2,3,4])#列表形式

#删除
obj=HostGroup.objects.get(id=1)#获取到主机组对象
obj.hobj.remove(2)#删除Host表中id=2的主机
obj.hobj.add(2,3,4)#多个删除
obj.hobj.remove(*[1,2,3,4])#列表形式

#清除
obj.hobj.clear() #清除HostGroup中等于gid等于1的对应的所有主机

#修改
obj=HostGroup.objects.get(id=1)#获取到主机组对象
obj.hobj.set(2)#更新
obj.hobj.set([1,2,3,4])#注意不带*,数据库只保存1,2,3,4

#
obj.hobj.all()#获取关联组的所有主机,返回QuerySET对象
八、jQuery中的ajax

 简介:

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

jQuery提供jQuery.ajax(url,[settings]方法:

参数:

  • async:(默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行
  • beforeSend(XHR):函数,发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。这是一个 Ajax 事件。如果返回false可以取消本次ajax请求。
  • complete(XHR, TS):函数,请求完成后回调函数 (请求成功或失败之后均调用)。参数: XMLHttpRequest 对象和一个描述成功请求类型的字符串。 Ajax 事件
  • data:发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。如果为数组,jQuery 将自动为不同值对应同一个名称。如 {foo:["bar1", "bar2"]} 转换为 "&foo=bar1&foo=bar2"。
  • dataType:预期服务器返回的数据类型,常见的有:

    "xml": 返回 XML 文档,可用 jQuery 处理。

    "html": 返回纯文本 HTML 信息;包含的script标签会在插入dom时执行。

    "script": 返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了"cache"参数。'''注意:'''在远程请求时(不在同一个域下),所有POST请求都将转为GET请求。(因为将使用DOM的script标签来加载)

    "json": 返回 JSON 数据 。

    "text": 返回纯文本字符串

  • headers:一个额外的"{键:值}"对映射到请求一起发送。此设置被设置之前beforeSend函数被调用;因此,消息头中的值设置可以在覆盖beforeSend函数范围内的任何设置。
  • type: (默认: "GET") 请求方式 ("POST" 或 "GET"), 默认为 "GET"。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。
  • url:(默认: 当前页地址) 发送请求的地址。
  • traditional:如果你想要用传统的方式来序列化数据,那么就设置为true.
  • timeout:设置请求超时时间(毫秒)。此设置将覆盖全局设置。

回调函数:

如果要处理$.ajax()得到的数据,则需要使用回调函数。beforeSend、error、dataFilter、success、complete。

  • beforeSend 在发送请求之前调用,并且传入一个XMLHttpRequest作为参数。
  • error 在请求出错时调用。传入XMLHttpRequest对象,描述错误类型的字符串以及一个异常对象(如果有的话)
  • dataFilter 在请求成功之后调用。传入返回的数据以及"dataType"参数的值。并且必须返回新的数据(可能是处理过的)传递给success回调函数。
  • success 当请求之后数据返回触发调用。传入返回后的数据,以及包含成功代码的字符串。
  • complete 当请求完成之后调用这个函数,无论成功或失败。传入XMLHttpRequest对象,以及一个包含成功或错误代码的字符串。

 

 简单的ajax提交数据示例:

$.ajax({
  url: '/person',
  type: "POST",//提交方法
  data: {'name': wd,'age': "22"},  // 使用form表单发送数据 $("#formid").serialize(),
  dataType: "JSON",  // 内部会自动将返回的数据用JSON解析
  traditional: true,  // 设置发送数据可以是传统数据,比如k,v数据中v是列表
  success: function(data){    //data为服务器返回数据字符串
                 var obj=JSON.parse(data)//将返回数据序列化为json对象,若设置了dataType为json,返回的数据直接就是json对象

      console.log(data);
      location.reload();  // 刷新页面
      location.href = "某个地址";  // 跳转到某个页面
  },
error:function(){ }//发生未知错误执行 })
//后台返回json格式数据 return HttpResponse(json.dumps(data))
获取用户数据以及上传文件

1、获取单一数据(get),以单选为例

模板文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/" method="post" enctype="multipart/form-data">
    男:<input type="radio" name="gender" value=1>
    女:<input type="radio" name="gender" value=2>
    <input type="submit" value="提交" >
</form>
</body>
</html>

后台获取:

 data=request.POST.get('gender')
 print(data)

2、获取多个数据(getlist)

模板文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/" method="post" enctype="multipart/form-data">
    男:<input type="checkbox" name="gender1" value=1>
    女:<input type="checkbox" name="gender1" value=2>
    位置:<input type="checkbox" name="gender1" value=3>
    <input type="submit" value="提交" >
</form>
</body>
</html>

后台接收:

data=request.POST.getlist('gender1')
print(data)

3、用户上次文件

  • form 表单中需要添加:enctype="multipart/form-data"
  • 后台使用obj.thrunks接受文件内容

上传模板文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/index/" method="post" enctype="multipart/form-data">
    <input type="file" name="upload_file">
    <input type="submit" value="提交" >
</form>
</body>
</html>

对应后台接受文件

    if request.method=="POST":
        file_obj=request.FILES.get('upload_file')
        f = open(file_obj.name, "wb")
        for line in file_obj.chunks():
            f.write(line)
        f.close()
#或者
f = open(file_obj.name, "wb")
for line in file_obj:  # 循环对象本身会自动去file_obj.chunks()里面获取文件内容
    f.write(line)
f.close()

 4、获取请求中的其他信息(用户发送的所有信息都封装在了request中)

request.path_info#获取请求的url
request.environ#获取其他请求信息
request.environ['HTTP_ACCEPT_LANGUAGE']#比如http接受语言
request.FILES.get('key')#获取文件对象


#增加一个响应头内容
response = HttpResponse("字符串")
response['name']= 'wd'
return response
原文地址:https://www.cnblogs.com/wdliu/p/7587303.html