zoukankan      html  css  js  c++  java
  • Django之url定义和ORM框架的使用

    前言,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

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

  • 相关阅读:
    备忘asp.net core使用中间件实现IP白名单访问
    Unity asp.net 依赖注入框架Unity
    linunx命令学习_文件命令
    Css中的属性选择器
    Html页基础代码
    JSX简介
    Js对象与Json字符串的互转
    React中的函数式组件和类组件
    win文件夹上右键后以xx打开
    Java中的泛型1_泛型的概念
  • 原文地址:https://www.cnblogs.com/linu/p/9330104.html
Copyright © 2011-2022 走看看