• Django入门四之数据库相关


    1. 数据库设置

    在settings.py中配置数据库

    我首先使用的是sqlite3,所以配置如下

    2. 数据库的数据结构定义

      #blog/models.py

    #定义了一个表(Student),表里两个字段name,age
    from django.db import models
    
    class Student(models.Model):
        name = models.CharField(max_length = 50)
        age = models.IntegerField()

    3. 创建/同步数据库

    CMD进入项目目录,执行命令

    (DJANGO~1) F:Python ScriptDjango webwebsite>manage.py syncdb

    这时候,在目录中就会创建一个数据库文件

    我们用SQLiteStudio(点此下载)打开这个文件

    发现,Django会自动给我们创建一个id字段的主键

     已经创建了数据库后,还能再同步吗?

      • 此时我们如果在models.py的Student中新增一个字段,然后再执行 manage.py syncdb ,是不能同步在数据库的。必须先删除已存在的表,再 manage.py syncdb这样是冒险的,注意做好数据备份
      • 我们在 SQLiteStudio 新建表

     

      然后CMD中执行 

    (DJANGO~1) F:Python ScriptDjango webwebsite>manage.py inspectdb

       会出现要创建这些数据库的表,字段,需要的python代码,如图

     这里的代码,比我们自己写的会准确些,还规范吧?可以复制写入models.py

    也可以用命令导入进去

    (DJANGO~1) F:Python ScriptDjango webwebsite>manage.py inspectdb > blog/models.py

    运行命令后,这些都会导入进去,然后再修修改改

    4. 数据库的增删改查

    增删改查操作都可以在数据库软件中直接操作,但这里说的肯定不是这种方法,比较我们是为网站服务,肯定是在代码里动态实现

    - 4.1 增加

    #urls.py

    url(r'^blog/student_list/$','student_list')

      #views.py

    from django.http import HttpResponse
    from django.template import loader,Context
    from blog.models import Student
    
    def student_list(request):
        html = loader.get_template("student.html")
        # 第一种方法:增加两行数据
        stu1 = Student(name="Tom",age=25)
        stu1.save()
        stu2 = Student(name="Jay",age=32)
        stu2.save()
    
        # 第二种方法:这里示例展示的结果是第一种方法的
        stu = Student()
        stu.name = "Lin"
        stu.age = 41
        stu.save
    
        # 第三种方法:这里示例展示的结果是第一种方法的
        Student.objects.create(name="Chen",age=36)
    Student.objects.get_or_create(name="Chen",age=36) #这个能防止重复
    # 第四种方法:这里示例展示的结果是第一种方法的 stu = {"name":"Wong","age":18} Student.objects.create(**stu) studentList = Student.objects.all() context = Context({"studentList":studentList}) return HttpResponse(html.render(context))

      

    #student.html

    <body>
        {% for student in studentList %}
            <li>{{ student.id }},{{ student.name }},{{ student.age }}</li>
        {% endfor %}
    </body>

    由于增加数据是在函数里,所以我们必须先输入地址,使得函数得以运行,才能插入数据成功

    输出的就是我们插入的两行数据

    我们在SQLiteStudio查看一下,确实已经插入

    -4.2 查询

    #views.py  (其他文件和上面一样,不做修改)

    # 查询所有的数据,或者用切片限制行数(不支持负索引)
    studentList = Student.objects.all()
    studentList = Student.objects.all()[:10] 
    studentList = Student.objects.all().reverse[:2]  #不支持负索引,但可以用reversse解决
    
    # 对数据行进行筛选
    studentList = Student.objects.get(id=1)            #获取id是1的,返回不是集合,只能获取一行
    studentList = Student.objects.filter(age=25)       #选取age是25的
    studentList = Student.objects.exclude(name="Tom")  #排除name是Tom的
    
    
    # 对数据列进行筛选
    studentList = Student.objects.all().values("name","age")  #value 返回的是一个查询对象,用list(studentList)后,返回的是列表,列表里面是一个一个的字典,字典是这样的{"name":"?","age":"?"}
    studentList = Student.objects.all().values_list("name","age")  #value_list返回的也是查询对象,用list(studentList)后,返回的也是列表,列表里面是一个一个的元祖,元祖是这样("nameValue","ageValue")
    
    # 注意:筛选符号举例,用双下划线加关键词,更多筛选条件符号看下图
    studentList = Student.objects.filter(age__gt=20)
    studentList = Student.objects.filter(name__regex="^T") # 正则表达式查询
    studentList = Student.objects.filter(name__iregex="^t")# 正则表达式不区分大小写
    
    # 对选取的数据再进行排序
    studentList = Student.objects.all().order_by("age") #升序
    studentList = Student.objects.all().order_by("-age") #降序
    
    # 对数据进行去重操作
    # 一般情况,单词查询不会出现重复,但是对多次查询结果进行合并,就有可能出现重复
    stu1 = Student.objects.all()
    stu2 = Student.objects.get(id = 1)
    studentList = stu1|stu2  #将两次查询结果合并
    studentList = studentList.distinct()

      以上studentList都是一个查询object

      可以使用两种方法,列出查询结果的元素

    1. list(studentList)
    2. for student in studentLst ...

        更大筛选条件符号看下图

    -4.3 修改

    #views.py  (其他文件和上面一样,不做修改) 

       # 第一种方法
        Student.objects.filter(age = 25).update(name = 'Chow')
    
        # 第二种方法
        stu = Student.objects.get(id = 2)
        stu.name = 'Lee'
        stu.age = 45
        stu.save()

         结果如下

      

    -4.4 删除

    #views.py  (其他文件和上面一样,不做修改) 

    Student.objects.filter(age = 25).delete()

      -4.5 查询python语句对应的SQL语句  

    print str(Student.objects.all().query)

      # 反正就是最后加query就可以

    5.  数据库的外键

      5.1 如何增加添加外键

       #models.py

    注意:Teacher一定要放在Student之前,因为同步的时候代码是顺序执行,不放前面代码会执行错误

    from django.db import models
    
    class Teacher(models.Model):
        id = models.IntegerField(primary_key = True)
        name = models.CharField(max_length = 50)
        class Meta:
            db_table = 'teacher'
    
    class Student(models.Model):
        id = models.IntegerField(primary_key = True)
        name = models.CharField(max_length = 50)
        age = models.IntegerField()
        sex = models.CharField(max_length = 10)
        teacher = models.ForeignKey(Teacher,related_name = "stu_teacher")
        class Meta:
            db_table = 'student'

      然后再cmd执行同步命令

    (DJANGO~1) F:Python ScriptDjango webwebsite>manage.py syncdb

      然后在表中填入一些数据吧(小细节:得先填入teacher表,才能填写student表,不然会提交失败

    #teacher

    #student

    重点在这里

    #views.py

    from django.template import loader,Context
    from blog.models import Student,Teacher
    
    def student_list(request):
        html = loader.get_template("student.html")
    
        # 外键的两种获取方法
        # 第一种,如果前面related_name没有填的话,这里stu_teacher改为set就可以
        teacher = Teacher.objects.get(id=1)
        studentList = teacher.stu_teacher.all()
    
        # 第二种
        studentList = Student.objects.filter(teacher_id=1)
       
        context = Context({"studentList":studentList})
        return HttpResponse(html.render(context))

       #student.html

    <body>
        {% for student in studentList %}
            <li>{{ student.id }},{{ student.name }},{{ student.age }},{{ student.sex }},{{ student.teacher.name }}</li>
        {% endfor %}
    </body>

     两种方法输出的结果都是一样的

     6. 用Shell来测试SQL语句

      如何进入shell模式呢

      首先如果有venv,得先进入venv,然后cd到项目所在目录

      运行:python manage.py shell

    (DJANGO~1) F:Python ScriptDjango webwebsite>python manage.py shell

      

     7. annotate,计数,求和,平均数

      首先当然是先进入Shell模式

    (DJANGO~1) F:Python ScriptDjango webwebsite>python manage.py shell
    Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>>

      导入相关模块和函数方法

    from blog.models import Student,Teacher
    from django.db.models import Counts,Avg,Sum

    # 方法还有Max,Min,StdDev(标准差),Variance(方差)

      先展示一下现有数据

      1. 计数

      目的:查询每个老师的学生数量(teacher别,对id进行计数)

      注意values和values_list的区别

      第一种

    >>> Student.objects.values("teacher").annotate(Count("id"))
    [{'teacher': 1, 'id__count': 3}, {'teacher': 2, 'id__count': 1}]

      第二种

    >>> Student.objects.values_list("teacher").annotate(Count("id"))
    [(1, 3), (2, 1)]
    >>>Student.objects.values_list("teacher","sex").annotate(Count("id"))
    [(1, u'u5973', 1), (1, u'u7537', 2), (2, u'u7537', 1)]

      2. 求平均数

    >>> Student.objects.values("sex").annotate(ave_age=Avg("age"))
    [{'ave_age': 21.0, 'sex': u'u5973'}, {'ave_age': 21.666666666666668, 'sex': u'u7537'}]

      3.求和

    >>> Student.objects.values("sex").annotate(sum_age=Sum("age"))
    [{'sum_age': 21, 'sex': u'u5973'}, {'sum_age': 65, 'sex': u'u7537'}]

     8. aggregation

    9. 多对多关系

      表与表之间既有一对多的关系也有多对多的关系

      举例说明

    • 一对多:一篇文章只能有一个作者,一个作者却可以写多篇文章
    • 多对多:一个学生能参加多个兴趣小组,一个兴趣小组也能招揽多个学生

    图省事可以这样填,只填一个表

    models.py 上面的写法是简便写法

    最好按下面来

    因为menbership这个表我们可以做更多的扩展 

     

     数据提取方法:

     第一种

    # 查出喜欢篮球的所有学生
    >>>from blog.models import Student,Teacher,Group
    >>>group = Group.objects.get(id=1)
    >>>group.members.values('name')
    [{'name': u'u9648u4eae'}, {'name': u'u9648u751f'}, {'name': u'u674eu5a77'}

    第二种

    # 查出学生id=2喜欢什么项目
    >>>student = Student.objects.get(id=2)
    >>> student.group_set.values_list("name")
    [(u'u8db3u7403',), (u'u7beeu7403',)]

  • 相关阅读:
    Tita 360 评估:新员工转正评估模版
    360反馈实例实例:如何给他人的弱点进行反馈
    数据库无法查询中文问题的解决过程
    sql server中判断表或临时表是否存在的方法
    5G网络
    Sqlserver中使用DBLINK
    Oracle 11g 安装图文教程
    SqlServer的Pivot和Unpivot用法
    ORACLE常用傻瓜問題1000問
    SqlServer的PIVOT、UNPIVOT将行转成列,列传成行
  • 原文地址:https://www.cnblogs.com/wongbingming/p/6901504.html
Copyright © 2020-2023  润新知