Django_02数据操作

2023-11-27  本文已影响0人  tzktzk1

数据操作--ORM模型

保存数据的途径---数据库
操作数据库的方法----

1.原生sql
2.ORM模型

ORM的概念

Object Relational Mapping(对象关系映射)

其主要作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来。 ... 当然这只是从对象到SQL的映射,还有从SQL到对象的映射,也是类似的过程。
有了ORM,我们不需要再写繁琐的sql语句,一切以python语法为准,通过ORM提供的API就可以操作数据库

主流的数据库都被Django 官方支持:

模型定义

以Event(发布会)为例,继承django自带的model类,并定义相应的字段
每个字段类都对应一种数据库字段格式

常用的数据库字段类型(ORM)

CharField

最常用的类型,字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。

BooleanField

布尔值类型。默认值是None

DateTimeField

日期时间类型。Python的datetime.datetime的实例。

IntegerField

整数类型,范围-2147483648 到 2147483647的值在 Django 支持的所有数据库中都是安全的。

附录:字段类型参考:https://docs.djangoproject.com/zh-hans/3.1/ref/models/fields/#field-types

常用字段选项(ORM)

null

如果是 True, Django 将在数据库中存储空值为 NULL。默认为 False。

default

该字段的默认值。可以是一个值或者是个可调用的对象,不能是一个可更改的对象(模型实例、list、set 等)。

unique

如果设置为 True,这个字段必须在整个表中保持值唯一。默认为False。若为True该字段可以成为一个唯一索引

verbose_name

字段的一个人类可读名称,如果没有给定详细名称,Django 会使用字段的属性名自动创建,并将下划线转换为空格。

剩余通用字段参考:https://docs.djangoproject.com/zh-hans/3.1/ref/models/fields/#field-options

模型字段定义代码参考:models.py

        from django.db import models
        
        # Create your models here.
        
        # 发布会模型--需要继承django自带的模型基类
        class Event(models.Model):
            # 名称--字符串 最大长度256
            name = models.CharField(max_length=256,null=False)
            # 地点
            address = models.CharField(max_length=256)
            # 人数
            limits = models.IntegerField(default=100)
            # 状态
            status = models.BooleanField(default=True)
            # 开始时间--允许为空
            start_time = models.DateTimeField(null=True)
字段命名约束:

Django不允许下面两种字段名:

1.与Python关键字冲突。这会导致语法错误。
2.字段名中不能有两个以上下划线在一起,因为两个下划线是Django的查询语法。
3.字段名不能以下划线结尾,原因同上。

由于你可以自定义表名、列名,上面的规则可能被绕开,但是请养成良好的习惯,一定不要那么起名。

模型方法

可以修改模型自带的str方法,这样在查询的时候,就能看到对应的数据信息了

        from django.db import models
        
        # Create your models here.
        
        # 发布会模型--需要继承django自带的模型基类
        class Event(models.Model):
            # 名称--字符串 最大长度256
            name = models.CharField(max_length=256,null=False)
            # 地点
            address = models.CharField(max_length=256)
            # 人数
            limits = models.IntegerField(default=100)
            # 状态
            status = models.BooleanField(default=True)
            # 开始时间--允许为空
            start_time = models.DateTimeField(null=True)
        
            # 覆盖对象对外的字符串表现形式
            def __str__(self):
                return self.name

对比:修改前

  >>> from sgin.models import Event
  >>> Event.objects.all()
  <QuerySet [<Event: Event object (1)>]>

对比:修改后:

  >>> from sgin.models import Event
  >>> Event.objects.all()
  <QuerySet [<Event: 测开发布会>]>

激活模型与数据迁移

激活模型

settings.py中添加应用名称以关联app

  INSTALLED_APPS = [
      'django.contrib.admin',
      'django.contrib.auth',
      'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
      'django.contrib.staticfiles',
      'demo', #注册app,
      'sgin'
  ]

配置数据库信息

默认使用的是sqlite,不需要配置,若要改成其他数据库,可以参考以下配置修改:如改成mysql

  # settings.py
  DATABASES = {
      'default': {
          'ENGINE': 'django.db.backends.mysql',    #数据库引擎
          'NAME': 'sqtp',                          #数据库名称
          'USER': 'root',                          #用户名
          'PASSWORD': 'devops',                    #密码
          'HOST': '192.168.21.140',                #数据库IP
          'PORT': '3306',                          #数据库端口
     }
  }

附录:数据库配置 https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial02/

模型迁移3步曲

迁移的内部过程

makemigrations命令---做语法预检查,生成操作数据库的命令,并不操作数据库,此时发生的错误都和数据库无关
migrate命令 将前一步的命令落实到数据库,此时发生的错误都和数据库有关

数据的增删改查API

调用模型API--- 通过模型的管理器
语法:模型类.objects.方法

增加

Model.objects.create(**kws)

修改

数据对象.字段=值
数据对象.save() #调用save才会保存到数据库
(千万不要用 Model.objects.update(**kws) 会把所有数据记录都更改)

删除

数据对象.delete()

查询---最丰富的操作

Model.objets.all() ---- 获取所有查询结果,返回QuerySet对象
Model.objets.filter(**kw) --- 条件过滤查询,返回QuerySet对象,不加参数效果和all()一样
Modle.objets.get() --- 获取单个数据对象 #没有匹配结果或者匹配结果超过1个都会报错查询是web中最频繁也是最丰富的操作

ORM执行查询参考:https://docs.djangoproject.com/zh-hans/3.1/topics/db/queries/

测试API--体验Django自带的命令行

python manage.py shell

Django自带的后台数据管理

用API手动创建的方式还是太麻烦,后续我们可以用API编写到接口里面
现在,我们先用Django自带的后台来管理数据

  1. 模型注册到admin.py

     # admin.py
     from django.contrib import admin
     from .models import Event
     # Register your models here.
     admin.site.register(Event)
    
  2. 创建管理员用户 python manage.py createsuperuser

  3. 新增数据

创建数据--发布会

功能迭代--修改视图

修改event视图

从数据库读取数据

event_list = Event.objects.all()

修改发布会详情视图 event_detail

修改视图event_detail
#发布会详情页
def event_detail(request,_id):
    # 从某处获取到当前页面的发布会数据对象
    event = Event.objects.get(id=_id)
    return render(request,'event_detail.html',{'event':event})

发布会详情页url可以设计成 event_detail/<int:event_id>
django会把event_detail/2类型的url 解析成 event_detail/<int:event_id >
event_id 可作为event_detail视图函数的参数,注意参数名需要相同
此为django解析foo/path/数字 类型的url的规则 若变化的值为字符串,将int改为str即可

修改url,增加ID
path('sgin/event_detail/<int:event_id>',views.event_detail),
修改发布会详情页 event_detail.html
{% extends 'base.html' %}
{% block title%}发布会详情页{% endblock %}
{% block content%}
  <div class="panel panel-info">
    <div class="panel-heading"> 发布会详情页 </div>
    <div class="panel-body">
      <p>发布会名称:{{ event.name }}</p>
      <p>发布会时间:{{ event.start_time }}</p>
      <p>发布会地址:{{ event.address }}</p>
      <p><a href="/sgin/events" class="btn btn-info">返回发布会列表</a></p>
    </div>
  </div>
{% endblock %}
修改列表页的URL,events.html
{% extends "base.html" %}
{% block title%}发布会管理{% endblock %}
{% block content%}
  <ul class="list-group">
    {% for event in event_list %}
      <li class="list-group-item text-center">
      <a href="/sgin/events/{{ event.id }}">{{ event }}</a>
      </li>
    {% endfor %}
  </ul>
{% endblock %}

需求2实现嘉宾列表和详情页

1.创建嘉宾数据模型对象
至少包括手机号,姓名,邮箱,和关联的发布会
2.模仿发布会列表和详情页,创建嘉宾视图路由以及模板页面
/sgin/guests/ #嘉宾列表
/sgin/guest_details/int:id #嘉宾详情页
现在的视图逻辑关系

image.png

按照需求,嘉宾需要与发布会进行关联,这个就涉及到了数据库表关联的关系。

数据库表关联

后端系统开发中, 数据库设计是重中之重。
特别是前后端分离的系统, 后端的职责基本就是数据管理, 开发的代码几乎都是围绕数据操作的。
虽然,这里不是专门讲数据库的, 但也必须讲解常用的 数据库表 和 表之间的关系 的设计 。

目前 使用的数据库系统 主要还是 关系型数据库 。
什么是关系型数据库?就是建立在关系模型基础上的数据库。
大家耳熟能详的mysql、oracle、 sqlserver、SQLite 都是,而 mongodb、Cassandra不是
而关系型数据库,设计的一个难点就是 各种表之间的关联关系 。
常见的3种关联关系就是: 一对多 , 一对一 , 多对多

例子
1对多: 1个老师可以上多门课程,对应多门课程

models.ForeignKey # 定义在多方

多对多:1个学生可以对应多门课程,1门课程也可以对应多个学生

models.ManyToManyField #定义在任意1方,只能定义在1方,不能双方都定义

多对1:1个男盆友对应1个女盆友...

models.OneToOneField # 定义在多方

嘉宾的与发布会的关系可先定为多对1

模型定义代码参考

  # 定义发布会关联嘉宾
  class Guest(models.Model):
      # django会自动帮你创建一个id字段作为主键
      # 关联发布会
      event = models.ForeignKey(Event,on_delete=models.CASCADE)  #CASCADE 如果删除了
  关联的发布会,该嘉宾也会被删除
      # 姓名 字符串 64 唯一
      name = models.CharField(max_length=64,unique=True)
      # 手机号 字符串 11   唯一
      phone = models.CharField(max_length=11,unique=True)
      # 邮箱 邮箱格式 xxx@yyy.zz
      email = models.EmailField()
      # 加入时间 --创建数据的时候就自动取当前时间 auto_now_add=True
      join_time = models.DateTimeField(auto_now_add=True)
      def __str__(self):
          return self.name

不要忘记运行命令同步到数据库。同时更新url和view.

urls.py

  # 嘉宾列表
      path('guests/',views.guests),
      # 嘉宾详情
      # 将guest_id/2类型的url 解析成guest_detail/<int:guest_id>
      # guest_id 可作为guest_detail视图函数的参数,注意参数名需要相同
      path('guest_detail/<int:guest_id>',views.guest_detail),

views.py

# 嘉宾列表
def guests(request):
    # 从数据库获取所有嘉宾
    guest_list = Guest.objects.filter()
    # 返回页面并填充数据
    return render(request,'guests.html',{'guest_list':guest_list})
# 嘉宾详情
def guest_detail(request,guest_id):
    # 根据获取的ID取对应的嘉宾
    guest = Guest.objects.get(pk=guest_id)
    # 返回页面并且填充嘉宾
    return render(request,'guest_detail.html',{'guest':guest})

最后:网页模板

guests.html

{% extends 'base.html' %}
{% block content %}
    <ul class="list-group">
       {% for guest in guest_list %}
            <li class="list-group-item text-center"><a href="/sgin/guest_detail/{{ guest.id }}">{{ guest.name }}</a></li>
       {% endfor %}
    </ul>
{% endblock %}

guest_detail.html

{% extends 'base.html' %}
{% block content %}
    <div class="panel-info panel">
        <div class="panel-heading"> 嘉宾详情页 </div>
        <div class="panel-body">
        <p>参与发布会:{{ guest.event }}</p>
        <p>姓名:{{ guest.name }}</p>
        <p>手机号:{{ guest.phone }}</p>
        <p>邮箱:{{ guest.email }}</p>
        <p>加入时间:{{ guest.join_time }}</p>
        <p><a href="/sgin/guests" class="btn btn-info">返回列表</a></p>
    </div>
    </div>
{% endblock %}

附录

模型字段参考:https://docs.djangoproject.com/zh-hans/3.1/ref/models/fields/#field-types
数据库配置:https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial02/
数据库访问优化:https://docs.djangoproject.com/zh-hans/3.1/topics/db/optimization/
字段命名限制:https://docs.djangoproject.com/zh-hans/3.1/topics/db/models/#field-name-restrictions
模型方法:https://docs.djangoproject.com/zh-hans/3.1/topics/db/models/#model-methods
模型管理器:https://docs.djangoproject.com/zh-hans/3.1/topics/db/managers/
ORM执行查询:https://docs.djangoproject.com/zh-hans/3.1/topics/db/queries/
QuerySetAPI参考:https://docs.djangoproject.com/zh-hans/3.1/ref/models/querysets/

上一篇下一篇

猜你喜欢

热点阅读