zoukankan      html  css  js  c++  java
  • Django-models & QuerySet API

    django中配置mysql数据库 

    1,首先配置settings.py。

          一是在INSTALLED_APPS里面加入app名称;

           二是配置数据库相关信息

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01'   #加上这一行,app名
    ]
    DATABASES = {    #配置数据库信息
        'default': {
            # 'ENGINE': 'django.db.backends.sqlite3',
            # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
            "ENGINE": 'django.db.backends.mysql',  #使用mysql数据库引擎
            'NAME': 'mydb',       #数据库名
            'HOST': 'localhost',   #ip
            'PORT': '3306',        #端口,注意是字符串
            'USER': 'root',      #用户名
            'PASSWORD': 'password'   #密码
        }
    }
    要先创建mydb数据库: > create database mydb charset utf8;
    
     
    View Code

    定义数据库表结构  models.py

    使用orm框架,不需要编写原生的sql语句

    from django.db import models
    class Person(models.Model):         #一个类对应一张表
        name = models.CharField(max_length=64)  # 字符串类型,必须加参数max_length  
        age = models.IntegerField()        #整数类型
        def __str__(self):     # 获取Person的对象时,显示name以便于区别
            return self.name 

    常用字段

    IntegerField  - 整型
    BooleanField  - 布尔值类型
    NullBooleanField  - 可以为空的布尔值
    CharField     - 字符串类型 必须提供max_length参数,字符长度
    TextField      - 文本类型
    EmailField     - 一个带有检查 Email 合法性的 CharField
    GenericIPAddressField      IP地址
    URLField        URL类型
    SlugField  - 字符串类型,只包含字母,数字,下划线或连字符
    CommaSeparatedIntegerField   - 字符串类型,格式必须为逗号分割的数字
    UUIDField   uuid类型
    DateTimeField     - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
    DateField   - 日期格式 YYYY-MM-DD
    TimeField   - 时间格式 HH:MM[:ss[.uuuuuu]]
    FloatField(Field)    - 浮点型
    DecimalField(Field)   - 10进制小数
    BinaryField(Field)    - 二进制类型

    参数

    null     为True时,数据库里的字段可以为空,如果想要生效需要设置blank=True。
    blank    为True时,admin中可以为空。但是不限制数据库,要想限制数据库里,需要设置null。
    choices   选择框。例如 gender = models.CharField(max_length=6, choices=gender_choices, default='male')
    default   字段默认值
    editable   默认都可以修改,如果为false,admin上面不可修改且不显示,但是数据库可以改
    error_messages   自定义错误信息,是字典类型
    help_text   该字段的提示信息
    unique    值唯一
    verbose_name   显示的字段名称

    更多字段查看官网:https://docs.djangoproject.com/en/2.1/ref/models/fields/ 

    class Person(models.Model):
        name = models.CharField(max_length=64, unique=True)
        age = models.IntegerField()
        birthday = models.DateField()
        gender_choices = ((u'male', ''), (u'female', ''))  #二选一
        gender = models.CharField(max_length=6, choices=gender_choices, default='male')  #默认为male
        blog_url = models.URLField(verbose_name="网址")  #admin显示为网址
        email = models.EmailField(help_text="写入一个类似123@qq.com的格式")   #字段下方有提示
        host = models.GenericIPAddressField(null=True, blank=True)  #可以为空
        def __str__(self):
            return self.name
        class Meta:         #修改admin显示的表名
            verbose_name_plural = '个人信息'  
    View Code

     创建表

    # python manage.py makemigrations
    #  python manage.py migrate

    QeurySet API

    数据库接口相关的接口叫queryset api。从数据库中查询出来的结果一般是一个QuerySet集合。

    创建数据

    >python manage.py shell

    >>> from app01.models import Person

    #方法一:
    >>> Person.objects.create(name='lily',age=20)
    <Person: lily>
    >>> Person.objects.create(name='jack',age=28)
    <Person: jack>
    #方法二: >>> p=Person(name='beibei',age=20)
    >>> p.save()    #此方法需save保存生效
    >>> p.name 'beibei' >>> p.age 20

    批量添加

    >>> Person.objects.bulk_create([Person(tname='老唐',gender='male'),
    Person(tname='老陈',gender='female')]) [<Person: 老唐>, <Person: 老陈>] # 批量添加

    查询数据

    all 获取所有对象列表

    >>> Person.objects.all()  #查询所有
    <QuerySet [<Person: lily>, <Person: jack>, <Person: beibei>, <Person: hei>]>
    >>> Person.objects.all()[:3]  #切片操作
    <QuerySet [<Person: lily>, <Person: jack>, <Person: beibei>]>
    >>> obj_list = Person.objects.all()
    >>> for i in obj_list:     #迭代对象列表
    ...     print(i.name,i.age)
    ...
    lily 22
    jack 28
    beibei 20
    hei 1
    >>>

    filter  过滤,返回符合条件的一批对象,列表

    >>> Person.objects.filter(id=1)
    <QuerySet [<Person: lily>]>
    >>> Person.objects.filter(name='lily',age=22) #多个条件逗号分隔
    <QuerySet [<Person: lily>]>
    
    #模糊查询,contains,endswith,startswith,range,regex
    >>> Person.objects.filter(name__contains='bei')  #contains 包含
    >>> Person.objects.filter(name__icontains='BEI')  #icontains 包含,不区分大小写
    >>> Person.objects.filter(name__startswith='ja')   #startswith
    >>> Person.objects.filter(name__endswith='ck')   #endswith
    >>> Person.objects.filter(age__range=[20,30])     #range范围
    >>> Person.objects.filter(name__regex='^bei')  #regex正则
    #时间类型 year,month,week,day
    >>> models.Person.objects.filter(birthday__year=1990)  # __year
    >>> models.Person.objects.filter(birthday__month=12)   # __month
    # 大小 gt,lt,gte,lte
    >>> models.Person.objects.filter(age__lte = 20)
    # 一个表里面两个字段大小对比 F()
    >>>  from django.db.models import F
    >>>  models.Person.objects.filter(age__lt=F('birthday')) # age小于birthday
    等同于sql:select age,birthday from Person where age < birthday;
    >>> models.Person.objects.filter(age__lt=F('birthday')/2) # 运算

      Q() 方法  复杂查询 and( , )  or( | )   not( ~ )

    from django.db.models import Q
    >>> s = School.objects.get(school_name='深大')
    >>> Student.objects.filter(Q(age__gt=20)|Q(school=s))  # or
    <QuerySet [<Student: 小南>, <Student: 小丽>]>
    >>> Student.objects.filter(Q(age__gt=20),Q(school=s))    #and
    <QuerySet [<Student: 小南>]>
    >>> Student.objects.filter(Q(age__gt=20),~Q(school=s))  # and,not
    <QuerySet [<Student: 小丽>]>
    #可以使用Q()和普通查询结合,但是Q必须放在前面
    >>> Student.objects.filter(Q(age__gt=20),~Q(school=s),sname__icontains='')         
    <QuerySet [<Student: 小丽>]>

    values  返回一个大列表。列表里的元素是字典,而不是queryset对象列表。每个字典代表一个对象

       values_list  列表里面的元素是元祖

    >>> Student.objects.values()
    <QuerySet [{'id': 13, 'sname': '小南', 'age': 34, 'school_id': 8, 'status': 'registered'}, {'id': 14, 'sname': '小北'
    , 'age': 30, 'school_id': 5, 'status': 'registered'}, .....}]>
    
    >>> models.Person.objects.filter(id__gt=3).values()
    <QuerySet [{'id': 4, 'name': '小陈', 'age': 7, 'birthday': datetime.date(1992, 12, 12)}]>
    >>> models.Person.objects.filter(id__gt=3).values('name','age')
    <QuerySet [{'name': '小陈', 'age': 7}]>

    exclude  排除

    models.Person.objects.filter(birthday__month=12).exclude(age__gt=12)
    <QuerySet [<Person: 小陈>]>

    oder_by 排序

    >>> models.Person.objects.order_by('birthday')[0]  #排序完后取第一条

    get  返回与查找条件相匹配的一个对象

     注意: 如果找到多个对象,则会报错:MultipleObjectsReturned

                如果没有找到对象,则会报错:DoesNotExist

    >>> Person.objects.get(name='jack')
    <Person: jack>
    >>> Person.objects.get(name='jack').name
    'jack'
    >>> Person.objects.get(name='jack').age
    28

    聚合 aggregate

    >>> Student.objects.count()  #统计个数
    3
    >>> from django.db.models import Max,Min,Avg,Sum
    >>> Student.objects.all().aggregate(Max('age'),Min('age'),Avg('age'),Sum('age'))
    {'age__max': 35, 'age__min': 30, 'age__avg': 33.0, 'age__sum': 99}
    >>> Student.objects.all().aggregate(sum_of_age=Sum('age'))   #自定义聚合名字
    {'sum_of_age': 99}
    
    from django.db.models import Count    #关联关系的count
    >>> obj = School.objects.annotate(Count('student'))
    >>> obj
    <QuerySet [<School: 北大>, <School: 深大>]>
    >>> obj[0].student__count
    2
    >>> for i in obj:
    ... if i.school_name == '深大':
    ... print(i.student__count)
    ...
    2

    修改数据

    #修改一条数据
    >>> p = Person.objects.get(name='hei')
    >>> p.name='kangkang'
    >>> p.age=24
    >>> p.save()
    # 批量修改
    >>> Person.objects.filter(age=28).update(age=29)
    1
    >>> Person.objects.all().update(age=0)  
    4

      >>> from django.db.models import F
      >>> Student.objects.update(age=F('age')+10)  # age统一+10
      3

    删除数据

    >>> Person.objects.filter(name__contains='kang').delete()  
    (1, {'app01.Person': 1})   #删除了一条数据

    另一种方法:通过admin页面对数据进行增删改查

    1,创建admin用户名密码 

    >python manage.py createsuperuser 

    2,在应用下admin.py中引入自身的models模块(或里面的类)

    vim admin.py

    from django.contrib import admin
    from .models import Person
    admin.site.register(Person)

    3, python manage.py runserver 

    访问127.0.0.1:8000/admin可以在后台页面看到app01站点下的Person类。

    (补充)关系型字段

    多对一    ForeignKey
    多对多   ManyToManyField

    例如:学生跟老师是多对多关系,学生跟学校是多对一关系:

    from django.db import models
    
    # Create your models here.
    class School(models.Model):
        school_name = models.CharField(max_length=64,unique=True)
        city = models.CharField(max_length=64)
        website = models.URLField()
        def __str__(self):
            return self.school_name
    class Teacher(models.Model):
        tname = models.CharField(max_length=64)
        gender = models.CharField(max_length=32)
        def __str__(self):
            return self.tname
    class Student(models.Model):
        sname = models.CharField(max_length=64)
        age = models.IntegerField()
        teacher = models.ManyToManyField(Teacher)  #跟老师多对多
        school = models.ForeignKey(School,on_delete=models.CASCADE)  #跟学校,多对一
        def __str__(self):
            return self.sname
    vim models.py

    models.ForeignKey()   python3里面需要加上on_delete参数,CASCADE:此值设置,是级联删除。否则会报错

    生成数据表:

    >python manage.py makemigrations formapp
    >python manage.py migrate formapp     #  Django会自动创建一个中间连接表student_teacher来表示多对多关系

     通过关联关系在命令行添加数据:

    #添加学生
    #方法一:
    >>> t1=Teacher.objects.get(tname='老唐')
    >>> s1=School.objects.get(school_name='北大')
    >>> t1.student_set.create(sname='小北',age=23,school=s1)
    <Student: 小北>
    #方法二:
    >>> S=Student(sname='小南',age=22,school=School.objects.get(city='深圳'))
    >>> S.save()
    >>> t2=Teacher.objects.get(tname="老陈") >>> S.teacher.add(t2) >>> S.save() #保存生效 >>> S.school <School: 深大> >>> S.teacher <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x0000000003EEC748> >>>S.teacher.values() <QuerySet [{'id': 4, 'tname': '老陈', 'gender': 'female'}]>

    从数据库可以看到关联关系:

    ForeignKey类型

    from formapp.models import Student, School, Teacher
    stu = Student.objects.get(sname='小北')
    sch = School.objects.get(school_name='清华')
    stu.school = sch 
    stu.save()   #保存生效

      删除数据:

       学生- 学校,多对一。  删除学校,会把对应的学生也给删掉, 因为 on_delete= CASCADE。会删除包含foreignKey的学生对象。

    >>> s=models.School.objects.get(school_name='深大')
    >>> s.delete()
    (4, {'formapp.Student_teacher': 1, 'formapp.Student': 2, 'formapp.School': 1})

    ManyToMany类型

    s1 = Student.objects.get(sname='小冬')
    t1 = Teacher.objects.get(tname="老陈")
    t2 = Teacher.objects.create(tname='老严')
    s1.teacher.add(t1, t2)   
    print(s1.teacher.values())
    ---<QuerySet [{'id': 4, 'tname': '老陈', 'gender': 'female'}, {'id': 11, 'tname': '老严', 'gender': ''}]>

     删除数据:

     学生-老师,多对多关系。删除老师不会删除对应的学生,只会删除关联关系。

    >>> t = models.Teacher.objects.get(tname='老陈')
    >>> t.delete()
    (3, {'formapp.Student_teacher': 2, 'formapp.Teacher': 1})

     反向关联查询

    student表里面写了 ForeignKey, ManyToMany。school和teacher表里并没有写,但是他们可以通过反向关联,查找到对应的student:

    >>> School.objects.get(school_name='北大').student_set
    <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x0
    000000003F57908>
    >>> School.objects.get(school_name='北大').student_set.select_related()
    <QuerySet [<Student: 小北>, <Student: 小丽>]>
    
    >>> Teacher.objects.last().student_set
    >>> Teacher.objects.last().student_set.select_related()
    <QuerySet [<Student: 小丽>, <Student: 小北>, <Student: 小南>]>

    从外部的脚本调用Django的models表

    import os, sys
    PROJECT_DIR = os.path.dirname((os.path.dirname(os.path.abspath(__file__))))
    sys.path.append(PROJECT_DIR)   # 将django项目根目录加入到环境变量
    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'  # 引入django的配置文件
    import django
    django.setup()           # 加载项目配置
    from formapp.models import Student  #导入formapp的Student表
    s = Student.objects.all()   # 操作数据库
    print(s)
    结果:
    <QuerySet [<Student: 小北>, <Student: 小南>, <Student: 小冬>]>
  • 相关阅读:
    网站链接
    CSS 初始化
    常见浏览器+浏览器内核
    sublime及其插件的安装
    数码时钟.js
    每天迁移MySQL历史数据到历史库Python脚本
    python和redis简单交互
    python和mongodb简单交互
    python3与mysql交互
    Red Hat Enterprise Linux 7.2修改主机名(hostname)
  • 原文地址:https://www.cnblogs.com/xiaobaozi-95/p/10180898.html
Copyright © 2011-2022 走看看