前言,Django安装

pip install django    # 官网安装最新版本
pip install django -i "https://pypi.doubanio.com/simple/"    # 指定安装源
pip install django --upgrate  # 更新Django
pip uninstall django    # 卸载django
pip install django==1.11.7 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com    # 安装指定版本django

一、Django项目的url的实现

1)创建django框架,

第一步:创建 django框架
先创建文件夹,再在cmd里面输入下面内容,项目:小说
django-admin startproject url定义

第二步
文件夹内出现相应的子文件,创建app
cd blog
python manage.py startapp blog #创建novel应用,会出现novel文件夹,里面有很多.py文件
python3 manage.py runserver 8080

第二步:访问
http://127.0.0.1:8000/ 首页

  pycharm创建Django框架非常简单,一步到位

2)自定义url网页。HttpResponse 返回前端字符串内容

from blog import views     # 添加内容

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^show_time',views.show_time)     # 添加内容
]
urls.py
from django.shortcuts import render,HttpResponse  # 补充的内容 

# Create your views here.

# 添加的函数
def show_time(req):    
    return HttpResponse("hello")
views.py

  3行内容实现了自定义网页

 3)以html文件返回给服务器。render 返回 html 内容

  在上面的基础上运行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hello world</h1>
</body>
</html>
templates/index.html
def show_time(req):
    return render(req,'index.html')    # 修改这里即可
view.py

 4)返回页面时间内容。技术点:html文件的{{ t }}  ===》views.show_time里面的变量t

  模板变量的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hello world {{ t }}</h1>
</body>
</html>
index.html
from django.shortcuts import render,HttpResponse
import time
# Create your views here.

def show_time(req):
    t=time.ctime()
    return render(req, 'index.html',locals())
views.py

 也可以换一种写法

HTML中  <h1>hello world {{ time }}</h1>

view.py中
def show_time(req):
    t=time.ctime()
    return render(req, 'index.html',{"time":t})

  4.1)模板变量的使用

第一种:直接获取到变量
<h1>hello {{ name }}</h1>
第二种:获取到列表,使用索引取值
<h1>hello {{ name.0 }}</h1>
<h1>hello {{ name.1 }}</h1>
第三种:获取到字典,使用key取值
<h1>hello {{ name.name }}</h1>
第四种:获取到对象,使用对象属性取值
<h1>hello {{ name.name }}</h1>
html中对python变量的获取

 4.2)模板过滤器

    语法格式:     {{obj|filter:param}}

   # 1  add          :   给变量加上相应的值
   #
   # 2  addslashes   :    给变量中的引号前加上斜线
   #
   # 3  capfirst     :    首字母大写
   #
   # 4  cut          :   从字符串中移除指定的字符
   #
   # 5  date         :   格式化日期字符串
   #
   # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
   #
   # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值
View Code

   使用示例

#value1="aBcDe"
{{ value1|upper }}<br>

#value2=5
{{ value2|add:3 }}<br>

#value3='he  llo wo r ld'
{{ value3|cut:' ' }}<br>

#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br>

#value5=[]
{{ value5|default:'空的' }}<br>

#value6='<a href="#">跳转</a>'

{{ value6 }}

{% autoescape off %}
  {{ value6 }}
{% endautoescape %}

{{ value6|safe }}<br>

{{ value6|striptags }}

#value7='1234'
{{ value7|filesizeformat }}<br>
{{ value7|first }}<br>
{{ value7|length }}<br>
{{ value7|slice:":-1" }}<br>

#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}<br>
    value9='hello I am yuan'
View Code

 4.3){% if %} 模板控制语句 if 判断

{% if num >= 100 and 8 %}

    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}

{% elif num < 100%}
    <p>num小于100</p>

{% else %}
    <p>num等于100</p>

{% endif %}



{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{% if obj1 and obj2 or obj3 %}  
if 判断

4.4){% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>


#在标签里添加reversed来反序循环列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

#{% for %}标签可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}


#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息

1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:

    
    {% for object in objects %}   
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {{ object }}   
        </li>  
    {% endfor %}  
    
# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值
# 在其他非循环的地方,你的forloop变量仍然可用


#{% empty %}

{{li }}
      {%  for i in li %}
          <li>{{ forloop.counter0 }}----{{ i }}</li>
      {% empty %}
          <li>this is empty!</li>
      {% endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55
{% for %}

5)加上jquery-3.2.1.min.js 静态文件渲染

第一步:找到存放位置
在顶级目录下创建static文件夹,存放jquery-3.2.1.min.js文件

第二步:添加配置路径。settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS=(os.path.join(BASE_DIR,"static"),)  添加位置

第三步:html加入文件

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    $("h1").css("color","red")
</script>

 

特别注意:
<script src="/static/jquery-3.2.1.min.js"></script>
这里的static对应的是。STATIC_URL = '/static/' 这里的

STATICFILES_DIRS=(os.path.join(BASE_DIR,"static"),)
这里对应的是文件夹的static名字

 6)引用jquery的推荐方法

<head>
    <meta charset="UTF-8">
    {% load staticfiles %}     # 增加的方法
    <title>Title</title>
</head>
<body>
<h1>hello world {{ time }}</h1>
{#<script src="/static/jquery-3.2.1.min.js"></script>#}     原来的方法
<script src="{% static 'jquery-3.2.1.min.js' %}"></script>  推荐使用的方法

 二、简单的注册页面写入

1)注册页面使用get 请求时

第一步:添加路由
urls.py里面  url(r"register",views.register)

第二步:定义视图函数
views.py里面添加函数
def register(request):
    print(request.GET)
    print(request.GET.get('user'))
    return render(request,'register.html')

第三步:templates里面添加 register.html 文件
 写入 register.html 文件
View Code
register.html文件
<body>
<h1>学生注册</h1>
<hr>
<form action="http://127.0.0.1:8000/register" method="get">
    <p>姓名<input type="text" name="user"></p>
    <p>年龄<input type="text" name="age"></p>
    <p>爱好<input type="checkbox" name="hobby" value="1">篮球
           <input type="checkbox" name="hpbby" value="2">篮球
           <input type="checkbox" name="hobby" value="3">篮球
    </p>
    <p><input type="submit">提交</p>
</form>
</body>
</html>
register.html

都可以实现
<form action="http://127.0.0.1:8000/register/" method="post">
<form action="/register/" method="post">

2)注册页面使用 post 请求时

需要关闭settings.py里面的安全机制      'django.middleware.csrf.CsrfViewMiddleware',。否则请求会发生错误

<body>
<h1>学生注册</h1>
<hr>
<form action="http://127.0.0.1:8000/register" method="post">
    <p>姓名<input type="text" name="user"></p>
    <p>年龄<input type="text" name="age"></p>
    <p>爱好<input type="checkbox" name="hobby" value="1">篮球
           <input type="checkbox" name="hpbby" value="2">篮球
           <input type="checkbox" name="hobby" value="3">篮球
    </p>
    <p><input type="submit">提交</p>
</form>
</body>
</html>
register.html
def register(request):
    print(request.POST)
    print(request.POST.get('user'))
    if request.method == "POST":
        return HttpResponse("success!")     # POST 请求之后返回的内容
    return render(request,'register.html')
register函数 post请求

 3)路由定义别名,实现动态的路由变化

第一步:路由定义别名
url(r"register", views.register,name="reg")

第二步:修改register.html
<head>
    {% load staticfiles %}
........
<form action="{% url 'reg' %}" method="post">
View Code

 4)url 路由分发(重点)

先在全局的urls文件中修改

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

from blog import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/',include('blog.urls'))   # 指向blog路由
]
View Code

再在app里面添加urls文件

from django.conf.urls import url,include
from django.contrib import admin

from blog import views

urlpatterns = [
    url(r'^show_time',views.show_time),
    url(r"register", views.register,name="reg"),
]
View Code

访问访问效果

由
http://127.0.0.1:8000/register
http://127.0.0.1:8000/show_time
变成了
http://127.0.0.1:8000/blog/register
http://127.0.0.1:8000/blog/show_time

5)url路由跳转。redirect (重点)

urlpatterns = [
    url(r'^show_time',views.show_time),     
    url(r"register", views.register,name="reg"),    注册界面
    url(r'login',views.login),     被跳转的登录界面
]

第二步:定义函数
def register(request):
    print(request.POST)
    user = request.POST.get('user')
    if user == "yuan":
        return redirect("/blog/login/")     #  跳转到指定的login路由
    return render_to_response("register.html")

def login(req):
    return render(req,"login.html")
View Code

6)补充内容

 # return render(request,'register.html')  建议用这个
等效于
 return render_to_response("register.html")

三、url的扩展,CBV模式(url==》class)

URL ---> 函数 ---> FBV
URL ---> 类  ---> CBV

1)匹配url规则模式,至上而下,匹配视图类

urlpatterns = [
    url(r'^admin/',admin.site.urls),
    url(r'^inx$',views.inx),
    # 由于前面已经有inx,要匹配到inxd,一定要在后面加$
    url(r'^inxd$',views.index),    
    
    url(r'^cbv$',views.CBV.as_view()),    # 匹配 views 里面的 class 
]
urls.py

2)视图类的创建

from django.views import View
class CBV(View):
    def get(self,request):
        return HttpResponse('CBV.GET')
        
    def post(self,request):
        return HttpResponse('CBV.POST')
views_class

3)自定义视图类的创建,类的扩展

from django.views import View
class CBV(View):
    def dispatch(self,request,*args,**kargs):
        result = super(CBV,self).dispatch(request,*args,**kargs)
        return result

    def get(self,request):
        # 根据请求头中的request method进行自动执行
        # return HttpResponse('CBV.GET')
        return render(request,'cbv.html')
        
    def post(self,request):
        return HttpResponse('CBV.POST')
views_class

四、orm对models中创建表的操作

1) 选择数据库的引擎

    第一种默认的数据库引擎。sqlite3

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

    第二种,mysql数据库

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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'books',    #你的数据库名称
        'USER': 'root',   #你的数据库用户名
        'PASSWORD': '', #你的数据库密码
        'HOST': '', #你的数据库主机,留空默认为localhost
        'PORT': '3306', #你的数据库端口
    }
}
mysql数据库

  需要替换驱动把mysqldb替换成pymysql

django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
所以,我们只需要找到项目名文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

2)创建表

第一步:确定配置文件加入了app
INSTALLED_APPS = [
    .................   
    'blog'
]

第二步:在models.py中写入class 表结构
# create table book(
#     name varchar(20),
#     price float(4,2),
# )
class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.FloatField()
    pub_date=models.DateField()

第三步:生成数据库
python manage.py makemigrations
python manage.py migrate
创建过程
from django.db import models

# Create your models here.

  # create table book(


# name varchar(20),
#     price float(4,2),
# )
class Book(models.Model):
    name = models.CharField(max_length=20)
    price = models.FloatField()
    pub_date = models.DateField()


class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
models.py
name=models.CharField(max_length=20,verbose_name="姓名")  起别名
price=models.IntegerField("价格")   # 起别名

如果后面继续增加表结构:python manage.py makemigrations

                                          python manage.py migrate

3)pycharm中查看创建的表

 

 

 4)单表内容的增删改

第一步:查看表字段

class Book(models.Model):
    name = models.CharField(max_length=20)
    price = models.FloatField()
    pub_date = models.DateField()
    author = models.CharField(max_length=32,null=False)
表结构

 前端网页显示

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

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .head{
            line-height: 40px;
            background-color: green;
            color: white;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="outer">
    <div class="head">标题</div>
    <div class="content">
        <a href="/addbook/">添加书籍</a>
        <a href="/update/">修改书籍</a>
        <a href="/delete/">删除书籍</a>
        <a href="/select/">查询书籍</a>
    </div>
    <div class="queryResult">
        {% for book in book_list %}
            <div>
                <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
            </div>
        {% endfor %}

    </div>

</div>
</body>
</html>
index.html

  配置相应的路由

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'index/', views.index),
    url(r'^addbook/',views.addbook),
    url(r'^update/', views.update),
    url(r'^delete/', views.delete),
    url(r'^select/', views.select),
]
urls.py

  4.1)根据表字段执行添加内容

def addbook(request):
    # 第一种
    # b = Book(name="python基础",price=99,author="egon",pub_date="2016-12-12")
    # b.save()

    # 第二种
    Book.objects.create(name="python进阶",price=69,author="egon",pub_date="2017-02-12")
    # Book.objects.create(**dic)   用户输入的字段完全一样的情况下
    return  HttpResponse("添加成功")
add

  4.2)更新修改表内容

def update(request):
    # 第一种,推荐使用,只对修改的字段赋值
    Book.objects.filter(author="egon").update(price=998)

    # 第二种,如果在sqlite可能会出错,实现原理,无论其他字段改没改,都重新赋值
    # b=Book.objects.get(author="oldboy")
    # b.price=120
    # b.save()
    # print(b)#<QuerySet [<Book: Book object>]>
    # print(type(b))
    return HttpResponse("更新成功")
update

  4.3)删除表内容

def delete(request):
    Book.objects.filter(author="oldboy").delete()
    return HttpResponse("删除成功"
delete

  4.4)查看表内容

def select(request):
    # 第一种查询全部
    book_list = Book.objects.all()
    # book_list = Book.objects.all()[:3]  # 列表特性,获取前3条记录
    # book_list = Book.objects.all()[::2]
    # book_list = Book.objects.all()[::-1]

    # book_list = Book.objects.filter(id=2) # 只要用filter取出来的就是集合
    # book = Book.objects.first()  # 获取第一个元素
    # book = Book.objects.last()   # 获取最后一个元素
    # book = Book.objects.get(id=2) # 只能获取到1个,多条报错
    
    # ret = Book.objects.filter(author="egon").values("name")    # 查询到作者是egon的写的所有书名
    # ret = Book.objects.filter(author="egon").values("name",'price')  # 列表中的字典形式,获取到指定的字段内容
    # ret = Book.objects.filter(author="egon").values_list("name", 'price')   # 列表中的元组形式

    book_list = Book.objects.exclude(author="egon").values("name",'price') # (排除)排除egon的内容
                                                    # values_list 该数据类型无法在前端调用的属性
    # book_list = Book.objects.all().values("name").distinct()    # 根据name字典去重
    book_cont = Book.objects.all().values("name").distinct().count()  # 确定有多少记录
    return render(request,'index2.html',{"book_list":book_list})
select练习示例

   查询归纳总结

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
#  <2>all():                 查询所有结果
#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------
#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列                                   
#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
#  <6>order_by(*field):      对查询结果排序
#  <7>reverse():             对查询结果反向排序
#  <8>distinct():            从返回结果中剔除重复纪录
#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。
# <11>first():               返回第一条记录
# <12>last():                返回最后一条记录
#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。
select总结

   models.gamedb_sun.objects.all().order_by('id').reverse()    反转需要和  order_by联合使用

start = models.gamedb_sun.objects.filter(data='2019-02-10').first()
end = models.gamedb_sun.objects.filter(data='2019-02-18').first()
start = start.id
end = end.id
print(start,end)
index_list = models.gamedb_sun.objects.filter(id__lt=end, id__gt=start)

 4.5)万能的模糊查询之双下划线

def select(request):
    #万能的  __
    # book_list=Book.objects.filter(price__gt=50).values("name","price")  # 筛选出大于50的
    book_list=Book.objects.filter(name__contains="P").values_list("name","price")  # 筛选出name字段含有"P"
                                    # __icontains  不区分大小写。前面含"i",则不区分大小写
    return render(request,'index2.html',{"book_list":book_list})
select __ 模糊查询

  双下划线(__)之单表条件查询总结

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感

models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and

startswith,istartswith, endswith, iendswith,
__模型查询

   4.6)查看调用的sql语句

  对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
setting+sql_log

 5)多表查询之一对多

class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")

    def __str__(self):
        return self.name

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

    def __str__(self):
        return self.name
models.py

 第一步查看表结构

app01_book

app01_publish 

第一种:查询生成python的出版社的信息
# book_obj=Book.objects.get(name="python")
# print(book_obj.name)
# print(book_obj.pub_date)
#
# #一对多:book_obj.publish--------一定是一个对象
# print(book_obj.publish.name)
# print(book_obj.publish.city)
# print(type(book_obj.publish))


第二种:查询记录(通过对象)
正向查询:A---> B正向:正向查按字段
    book_obj = Book.objects.get(name="python")
    pub_obj=book_obj.publish -----》书籍对象对应的出版社对象
    pub_obj.name
反向查询:B---> A反向:反向查按表名小写_set
    pub_obj = Publish.objects.filter(name = "人民出版社")
    pub_obj.book_set.all().values("name","price")

    
第三种:查询人民出版社出过的所有书籍名字和价格
#方式一:
# pub_obj=Publish.objects.filter(name="人民出版社")[0]
# ret=Book.objects.filter(publish=pub_obj).values("name","price")
# print(ret)

#方式二
# pub_obj = Publish.objects.filter(name="人民出版社")[0]
# print(pub_obj.book_set.all().values("name","price"))
#print(type(pub_obj.book_set.all()))

#方式三
# ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
# print(ret)
多表查询之一对多

 6)多表操作之一对多的增删改查

class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")   # 创建的约束,约束条件下,默认生成的表字段加上 _id

    def __str__(self):
        return self.name

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)
models.py

  app01_publish

 app01_book

    6.1)一对多中增加表内容

方式一    
Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)

方式二
publish_obj=Publish.objects.filter(name="人民出版社")[0]      # 找到人民出版社的id,赋值给book的publish
Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
create_add

    6.2)一对多中查询表内容

  正常查询

#查询人民出版社出过的所有书籍名字和价格
方式一:
pub_obj=Publish.objects.filter(name="人民出版社")[0]
ret=Book.objects.filter(publish=pub_obj).values("name","price")
print(ret)

#方式二
pub_obj = Publish.objects.filter(name="人民出版社")[0]
print(pub_obj.book_set.all().values("name","price"))
print(type(pub_obj.book_set.all()))
View Code

   __  匹配多表查询。filter 和 __   ==》 跨表查询

ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
print(ret)

#python这本书出版社的名字
ret2=Publish.objects.filter(book__name="python").values("name")
print(ret2)
ret3=Book.objects.filter(name="python").values("publish__name")
print(ret3)

ret4=Book.objects.filter(publish__city="北京").values("name")
print(ret4)

ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
print(ret5)
View Code

 7)多表操作之多对多

  7.1)ManyToManyField自动创建第三张虚拟的关系表

class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")    # 会自动生成多对多的book_author的关系表

    def __str__(self):
        return self.name

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)
    
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField(default=20)    
    
    def __str__(self):
        return self.name
models.py

       基本的查询

book_obj=Book.objects.get(id=3)
print(book_obj.authors.all())
print(type(book_obj.authors.all()))

author_obj=Author.objects.get(id=2)
print(author_obj.book_set.all())
多对多基本查询

      增加关系的表操作

通过对象的方式绑定关系
增加一条记录book_author的关系记录
book_obj=Book.objects.get(id=4)
author_obj=Author.objects.get(id=2)
book_obj.authors.add(author_objs)    
# 第4本书的作者是2号作者


增加多条记录book_author的关系记录
book_obj=Book.objects.get(id=4)
author_obj=Author.objects.all()
book_obj.authors.add(*author_objs)    
第4本书的作者是所有的作者搞的


解除某书与作者之间的关系
book_obj=Book.objects.get(id=4)
author_obj=Author.objects.all()
book_obj.authors.remove(*author_objs)    


解除某书与作者的id关系
book_obj=Book.objects.get(id=3)
author_obj=Author.objects.all()
book_obj.authors.remove(2)  # 指解除书的id为3的,作者为2的关系
View Code

     对比真实表比较查询。真实表的创建在后面

#alex出过的书籍名称及价格,真实表
ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
print(ret)

# ManyToManyField自动创建的虚拟表
ret2=Book.objects.filter(authors__name="alex").values("name","price","authors__name")
print(ret2)
真实与虚拟查询方法对比

      补充内容

from django.db import models

class Classes(models.Model):
    """
    班级表,男
    """
    titile = models.CharField(max_length=32)
    m = models.ManyToManyField('Teachers',related_name='sssss')

class Teachers(models.Model):
    """
    老师表,女
    """
    name = models.CharField (max_length=32)

class Student(models.Model):
    """
    学生表
    """
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.BooleanField()
    cs = models.ForeignKey(Classes,related_name='ssss') # cs,cs_id  1    3班



######################## 单表 ########################
# 增加
# Teachers.objects.create(name='root')
# obj = Teachers(name='root')
# obj.save()
# 查
# Teachers.objects.all()
# Teachers.objects.filter(id=1)
# Teachers.objects.filter(id=1,name='root')
# result = Teachers.objects.filter(id__gt=1)
# [obj(id,name),]
# result = Teachers.objects.filter(id__gt=1).first()
# 删除
# Teachers.objects.filter(id=1).delete()
# 改
# Teachers.objects.all().update(name='alex')
# Teachers.objects.filter(id=1).update(name='alex')

######################## 一对多 ########################
"""
班级:
id    name
 1    3班
 2    6班

学生
id   username    age    gender   cs_id
1      东北       181
2      东北1      1182
2      东北1      1181
"""
# 增加
# Student.objects.create(username='东北',age=18,gender='',cs_id=1)
# Student.objects.create(username='东北',age=18,gender='',cs= Classes.objects.filter(id=1).first() )
# 查看
"""
ret = Student.objects.all()
# []
# [ obj(..),]
# [ obj(1      东北       181),obj(2      东北1      1182),obj(..),]
for item in ret:
    print(item.id)
    print(item.username)
    print(item.age)
    print(item.gender)
    print(item.cs_id)
    print(item.cs.id)
    print(item.cs.name)
"""
# 删除
# Student.objects.filter(id=1).delete()
# Student.objects.filter(cs_id=1).delete()

# cid = input('请输入班级ID')
# Student.objects.filter(cs_id=cid).delete()

# cname = input('请输入班级名称')
# Student.objects.filter(cs_id=cid).delete()
# Student.objects.filter(cs__name=cname).delete()




######################## 多对多 ########################

# 多对多
"""
班级:
id  title
1    3班
2    4班
3    5班
老师:
id   title
 1    Alex
 2    老妖
 3    瞎驴
 4    Eric
 老师班级关系表(类):
id   班级id   老师id
 1     1        2
 2     1        3
 4     2        2
 5     2        3
 6     2        4
 7     1        5


# 增
obj = Classes.objects.filter(id=1).first() #1    3班
obj.m.add(2)
obj.m.add([4,3])

# obj = Classes.objects.filter(id=2).first() #1    3班
# obj.m.add(2)
# obj.m.add([4,3])

obj = Classes.objects.filter(id=1).first() #1    3班
# 删除
# obj.m.remove([4,3])
# 清空
obj.m.clear()
# 重置
obj.m.set([2,3,5])

# 查第三张表
# 把3班的所有老师列举
obj = Classes.objects.filter(id=1).frist()
obj.id
obj.titile
ret = obj.m.all() # 第三张表
# ret是一个 [ 老师1(id,name),obj(id,name)   ]

"""
View Code

 

班级:
id    name
 1    3班
 2    6班

class School:
    name = models.CharField(max_length=32)
 
 
class Classes(models.Model):
    """
    班级表,男
    """
    titile = models.CharField(max_length=32)
    # m = models.ManyToManyField('Teachers')      # 多对多
    # sch = models.ForeignKey(School)

老师:
id   title
 1    Alex
 2    老妖
 3    瞎驴
 4    Eric
class Teachers(models.Model):
    """
    老师表,女
    """
    name = models.CharField (max_length=32)

学生
id   username    age    gender   cs_id
1      东北       181
2      东北1      1182
2      东北1      1181
class Student(models.Model):
    """
    学生表
    """
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.BooleanField()
    cs = models.ForeignKey(Classes) #
    
    
示例:
    - 所有学生的姓名以及其所在班级名称,QuerySet
        stu_list = Student.objects.all()
        select * from tb;
        [obj,obj,obj,obj]
        
        stu_list = Student.objects.all().values("id",'username')
        select id,username from tb;
        [{"id":1,'username':'xx'},{id:'',username:''}]   
        
        stu_list = Student.objects.all().values_list("id",'username')
        [(1,'root'), (2,'alex')]
        
        
        stu_list = Student.objects.all().values('username',"cs__name")
        for row in stu_list:
            print(row['username'],row['cs__name'])
        
        stu_list = Student.objects.all().values('username',"cs__titile",“cs__fk__name”)
        
    - 找到3班的所有学生
        Student.objects.filter(cs__name='3班')
        
        obj = Classes.objects.filter(name='3班').first()
View Code

    7.2)聚合函数查询:aggregate(*args,**kwargs)

调用模块
from django.db.models import Avg,Min,Sum,Max,Count

ret=Book.objects.all().aggregate(Avg("price"))
ret=Book.objects.all().aggregate(Sum("price"))
ret=Book.objects.filter(authors__name="alex").aggregate(Sum("price"))
ret=Book.objects.filter(authors__name="alex").aggregate(alex_money=Sum("price"))
ret=Book.objects.filter(authors__name="alex").aggregate(Count("name"))
print(ret)

# 每一个作者出过的书的总价。涉及了分组
ret1=Book.objects.values("authors__name")
ret2=Book.objects.values("authors__name").annotate(Sum("price"))
print(ret2) 

# 每个出版社出版的价格最低的书
ret=Publish.objects.values("name").annotate(abc=Min("book__price"))
print(ret)
View Code

    7.3)引入F查询和Q查询

引入F,Q 函数
from django.db.models import Q,F
# 对数据进行加减,引入F
Book.objects.all().update(price=F("price")+10)

# 找到价格是87或者是GO的,条件或,引入 Q
ret = Book.objects.filter(Q(price=87)|Q(name="GO"))
# 找到不少GO的
ret = Book.objects.filter(^Q(name="GO"))
# Q查询也关键字查询组合使用,但Q查询一定要写在前面
ret=Book.objects.filter(Q(name="GO"),price=87)
print(ret)
View Code

    7.4)ORM的querySet集合对象特性。可节约内存的方式

ret = Book.objects.filter(price=100)
# 如果不使用ret,则不执行sql语句
for i in ret:  
    print(i.price)

if ret.exists():  # 仅仅是判断有没有值,不会把查询结果存在内存中
    print("ok")

节省内存,变化成迭代器
ret=ret.iterator()
print(ret)

for i in ret:
    print(i.name)
View Code

    7.5)models.py 创建第三张真实表的关系表

class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")

    def __str__(self):
        return self.name

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

    def __str__(self):
        return self.name


class Book_Author(models.Model):
    book=models.ForeignKey("Book")
    author=models.ForeignKey("Author")

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField(default=20)

    def __str__(self):
        return self.name
models.py

  表关系应用。虚拟表在上面

#创建第三张表
Book_Author.objects.create(book_id=2,author_id=2)
# 通过id为2的书的作者
obj=Book.objects.get(id=2)
print(obj.book_author_set.all()[0].author)

#alex出过的书籍名称及价格
ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
print(ret)
真实与虚拟查询方法对比

 8)模型中常用的字段类型参数

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes""No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
View Code

 9)field 重要参数

<1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)
View Code

 10)修改默认存储时间。默认存储会有6位毫秒

查看源码文件 django/db/backends/mysql/base.py
class DatabaseWrapper(BaseDatabaseWrapper):
    vendor = 'mysql'
    display_name = 'MySQL'
    # This dictionary maps Field objects to their associated MySQL column
    # types, as strings. Column-type strings can contain format strings; they'll
    # be interpolated against the values of Field.__dict__ before being output.
    # If a column type is set to None, it won't be included in the output.
    data_types = {
        'AutoField': 'integer AUTO_INCREMENT',
        'BigAutoField': 'bigint AUTO_INCREMENT',
        'BinaryField': 'longblob',
        'BooleanField': 'bool',
        'CharField': 'varchar(%(max_length)s)',
        'DateField': 'date',
        'DateTimeField': 'datetime(6)',
        '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(6)',
        'UUIDField': 'char(32)',
    }

分析需要更改DateTimeField这个的字段显示

在models.py中更改添加如下数据

from django.db.backends.mysql.base import DatabaseWrapper
DatabaseWrapper.data_types["DateTimeField"] = 'datetime'

class Alarm(models.Model):
    id = models.AutoField(primary_key=True)
    rule_name = models.CharField(max_length=128)
    state = models.CharField(max_length=128)
    cluster = models.CharField(max_length=128)
    start_time = models.DateTimeField('保存日期',auto_now_add = True)
    end_time = models.DateTimeField('最后修改日期',auto_now = True)
    rule_group_name = models.CharField(max_length=128)

 11)批量插入

class DemoView(APIView):
    def get(self, request):
        demolist = []
        for age in range(1,200):
            demodict = {}
            demodict["name"] = "test" + str(age)
            demodict["age"] = age
            demolist.append(Demo(name='test%s' % str(age),age=age))
        print(demolist)
        Demo.objects.bulk_create(demolist)
        return JsonResponse({"code": 200}, safe=False)

原文出处:https://www.cnblogs.com/yuanchenqi/articles/6083427.html

posted on 2018-08-03 10:34  可口_可乐  阅读(713)  评论(0编辑  收藏  举报