ORM实现数据的增删改查和创建表关系

pycharm链接数据库(MySQL)

三个位置查找数据库
    右侧上方database
    左下方database
    在配置文件的plugins插件搜索安装
    没有的话卸载安装

在使用对应的数据库前,需要下载对应数据库的驱动

django链接数据库(MySQL)

# 默认用的是sqkite3
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
# 首先应当创建一个数据库(day60)
1、在配置文件中配置
    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day60',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8',
        }
    }
2、代码声明
    django默认用的是mysqldb模块链接MySQL
    但是该模块的兼容性不好 需要手动改为用pymysql链接
    
    你需要告诉django不要用默认的mysqldb还是用pymysql
    # 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以
    import pymysql
    pymysql.install_as_MySQLdb()

Django ORM

'''
ORM    对象关系映射
作用:面向对象的代码能简单快捷的操作数据库
不足:封装程度太高,有时候sql语句的效率偏低,需要手动写sql语句
类                    表
对象                  记录
对象属性              记录某个字段对应的值
'''
# 在models.py中书写一个类
class User(models.Model):
    # id int primary_key auto_increment
    id = models.AutoField(primary_key=True)
    # username varchar(32)
    username = models.CharField(max_length=32)
    # password int
    password = models.IntegerField()

############数据库迁移命令##########################################################################
python3 manage.py makemigrations 将操作记录记录到小本本上(migrations文件夹)
如果出现No changes detected的报错,则执行python3 manage.py makemigrations --empty App App是你的应用名

python3 manage.py migrate  将操作真正的同步到数据库中
# 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令
##################################################################################################

class User(models.Model):
    # id int primary_key auto_increment
    id = models.AutoField(primary_key=True,verbose_name='主键')
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name='用户名')
    """
    CharField必须要指定max_length参数 不指定会直接报错
    verbose_name该参数是所有字段都有的 就是用来对字段的解释
    """
    # password int
    password = models.IntegerField(verbose_name='密码')

class Author(models.Model):
    # 由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
    # 所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
    # 也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写
    # username varchar(32)
    username = models.CharField(max_length=32)
    # password int
    password = models.IntegerField() 

字段的增删改查

# 字段的增加
  1.现在后端中加上你需要添加的字段,然后执行数据库迁移命令,可以在终端内直接给出默认值
  2.该字段可以为空
    info = models.CharField(max_length=32,verbose_name='个人简介',null=True)
  3.直接给字段设置默认值
    hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')
 
# 字段的修改
    直接修改代码然后执行数据库迁移的两条命令即可!

# 字段的删除
    直接注释对应的字段然后执行数据库迁移的两条命令即可!
    执行完毕之后字段对应的数据也都没有了

数据的增删改查

class User(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='主键',)
    username = models.CharField(max_length=32, verbose_name='用户名')
    password = models.IntegerField(verbose_name='密码')
models.py
<body>
<form action="" method="post">
    <p>username:
        <input type="text" name="username">
    </p>
    <p>password:
        <input type="text" name="password">
    </p>
    <input type="submit" value="登录">
</form>
</body>
index.html
<body>
<form action="" method="post">
    <p>username:
        <input type="text" name="username">
    </p>
    <p>password:
        <input type="text" name="password">
    </p>
    <input type="submit" value="注册">
</form>
</body>
reg.html
<body>
<h1 class="text-center">数据展示</h1>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table table-striped table-hover">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>username</th>
                        <th>password</th>
                        <th>action</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_obj in user_queryset %}
                        <tr>
                            <td>{{ user_obj.id }}</td>
                            <td>{{ user_obj.username }}</td>
                            <td>{{ user_obj.password }}</td>
                            <td>
                                <a href="/app01/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
                                <a href="/app01/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
user_list.html
<body>
<h1 class="text-center">编辑</h1>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <form action="" method="post">
                <p>username:<input type="text" name="username" class="form-control" value="{{ edit_obj.username }}"></p>
                <p>password:<input type="text" name="password" class="form-control" value="{{ edit_obj.password }}"></p>
                <input type="submit" class="btn btn-info btn-block" value="编辑">
            </form>
        </div>
    </div>
</div>
</body>
edit_user.html
from django.urls import re_path
from app01 import views
urlpatterns = [
    # 数据的查询
    re_path(r'^look_user/', views.look_user),
    # 数据的增加
    re_path(r'^add_user/',views.add_user),

    # 展示所有数据到前端
    re_path(r'^user_list/', views.user_list),
    # 编辑功能
    re_path(r'^edit_user/', views.edit_user),
    # 删除功能
    re_path(r'^delete_user/',views.delete_user),
]
urls.py
from django.shortcuts import render, HttpResponse, redirect
from app01 import models

def look_user(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        from app01 import models
        res = models.User.objects.filter(username=username)
        print(res)
        user_obj = res[0]
        print(user_obj)
        print(user_obj.username)
        # if models.User.objects.filter(username=username,password=password):
        #     return HttpResponse('登入成功')
        # else:
        #     return HttpResponse('输入错误')
    return render(request,'index.html')

def add_user(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if models.User.objects.filter(username=username):
            return HttpResponse('用户已经存在')
        else:
            res = models.User.objects.create(username=username,password=password)
            print(res)
            return HttpResponse('注册成功')
    return render(request,'reg.html')

def user_list(request):
    # 查询出用户表里面的所有数据
    user_queryset = models.User.objects.filter().all()
    return render(request, 'user_list.html', locals())

# 后端查询出用户想要编辑的数据对象,展示到前端页面供用户查看和编辑
def edit_user(request):
    # 获取url问号后面的参数
    edit_id = request.GET.get('user_id')
    # 查询当前用户想要编辑的数据对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 去数据库中修改对应的数据内容
        # 修改数据方式1
        # models.User.objects.filter(id=edit_id).update(username=username,password=password)
        '''将filter查询出来的列表中所有的对象全部更新,批量操作,只修改被修改的字段'''
        # 修改数据方式2
        edit_obj.username = username
        edit_obj.password = password
        edit_obj.save()
        '''当字段特别多的时候效率非常低,从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改'''
        # 跳转到数据的展示页面
        return redirect('/app01/user_list/')
    # 将数据对象展示到页面上
    return render(request,'edit_user.html',locals())

def delete_user(request):
    # 获取用户想要删除的数据的id值
    delete_id = request.GET.get('user_id')
    # 直接到数据库中找到对应的数据删除
    models.User.objects.filter(id=delete_id).delete()
    # 跳转到展示页面
    return redirect('/app01/user_list')
# 真正的删除功能应该需要二次确认
# 删除数据内部其实并不是真正的删除,程序员会给数据添加一个标识字段用来表示当前数据是否被删除,如果数据删除了仅仅只是将字段修改一个状态
views.py

# from app01 import models
res = models.User.objects.filter(username=username)
print(res)  # <QuerySet [<User: User object (3)>]>
'''
返回值可看成列表套数据对象的格式
返回值支持索引取值,切片操作,但不支持负数索引
但是不推荐使用索引的方式取值
user_obj = models.User.objects.filter(username=username).first()
filter括号内可携带多个参数,参数与参数之间默认是and关系
'''
user_obj = res[0]
print(user_obj)  # User object (3)
print(user_obj.username)  # 从form表单内输入的username的值
print(user_obj.password)  # 从form表单内输入的password的值

# 查询出表中的所有数据的两种方式
models.User.objects.filter()
models.user.objects.filter().all()

# from app01 import models
# 第一种方法
res = models.User.object.create(username=username,password=password)
# 返回值就是当前被创建的对象本身  User object (5)
# 第二种方法
user_obj = models.User(username=username,password=password)
user_obj.save()  # 保存数据

# 修改数据方式1
# models.User.objects.filter(id=edit_id).update(username=username,password=password)
'''将filter查询出来的列表中所有的对象全部更新,批量操作,只修改被修改的字段'''
# 修改数据方式2
edit_obj.username = username
edit_obj.password = password
edit_obj.save()
'''当字段特别多的时候效率非常低,从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改'''

models.User.objects.filter(id=delete_id).delete()
# 真正的删除功能应该需要二次确认 我们这里先不做后面会讲
# 删除数据内部其实并不是真正的删除 我们会给数据添加一个标识字段用来表示当前数据是否被删除了,如果数据被删了仅仅只是讲字段修改一个状态
    username    password    is_delete
      yuan        123           0
      chen        456           1

django orm中如何创建表关系

图书表
出版社表
作者表
作者详情表
"""
图书和出版社是一对多的关系 外键字段建在多的那一方 book
图书和作者是多对多的关系 需要创建第三张表来专门存储
作者与作者详情表是一对一
"""
from django.db import models
# Create your models here.
# 创建表关系  先将基表创建出来 然后再添加外键字段
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 总共八位 小数点后面占两位
    """
    图书和出版社是一对多 并且书是多的一方 所以外键字段放在书表里面
    """
    publish = models.ForeignKey(to='Publish')  # 默认就是与出版社表的主键字段做外键关联
    """
    如果字段对应的是ForeignKey,那么orm会自动在该字段的后面加_id
    如果你自作聪明的加了_id那么orm还是会在后面继续加_id
    后面在定义ForeignKey的时候就不要自己加_id
    """

    """
    图书和作者是多对多的关系 外键字段建在任意一方均可 但是推荐你建在查询频率较高的一方
    """
    authors = models.ManyToManyField(to='Author')
    """
    authors是一个虚拟字段 主要是用来告诉orm 书籍表和作者表是多对多关系
    让orm自动帮你创建第三张关系表
    """


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


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    """
    作者与作者详情是一对一的关系 外键字段建在任意一方都可以 但是推荐你建在查询频率较高的表中
    """
    author_detail = models.OneToOneField(to='AuthorDetail')
    """
    OneToOneField也会自动给字段加_id后缀
    所以你也不要自作聪明的自己加_id
    """

class AuthorDetail(models.Model):
    phone = models.BigIntegerField()  # 或者直接字符类型
    addr = models.CharField(max_length=32)


"""
    orm中如何定义三种关系
        publish = models.ForeignKey(to='Publish')  # 默认就是与出版社表的主键字段做外键关联
        authors = models.ManyToManyField(to='Author')
        author_detail = models.OneToOneField(to='AuthorDetail')
        
        ForeignKey
        OneToOneField
            会自动在字段后面加_id后缀
"""

# 在django1.X版本中外键默认都是级联更新删除的
# 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种
# 针对外键字段里面的其他参数 暂时不要考虑 如果感兴趣自己可以百度试试看
# django2.0后,定义外键(一对多关系)和一对一关系的时候需要加on_delete选项

多表操作

 一对多外键增删改查

 

# 一对多外键增删改
    #
    # 1  直接写实际字段 id
    # models.Book.objects.create(title='论语',price=899.23,publish_id=1)
    # models.Book.objects.create(title='聊斋',price=444.23,publish_id=2)
    # models.Book.objects.create(title='老子',price=333.66,publish_id=1)
    # 2  虚拟字段 对象
    # publish_obj = models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj)

    #
    # models.Publish.objects.filter(pk=1).delete()  # 级联删除

    # 修改
    # models.Book.objects.filter(pk=1).update(publish_id=2)
    # publish_obj = models.Publish.objects.filter(pk=1).first()
    # models.Book.objects.filter(pk=1).update(publish=publish_obj)

 

 

 

 多对多外键增删改查

 

# 如何给书籍添加作者?
    book_obj = models.Book.objects.filter(pk=1).first()
    # print(book_obj.authors)  # 就类似于你已经到了第三张关系表了
    # book_obj.authors.add(1)  # 书籍id为1的书籍绑定一个主键为1 的作者
    # book_obj.authors.add(2,3)

    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # author_obj2 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.add(author_obj)
    # book_obj.authors.add(author_obj1,author_obj2)
    """
    add给第三张关系表添加数据
        括号内既可以传数字也可以传对象 并且都支持多个
    """

    #
    # book_obj.authors.remove(2)
    # book_obj.authors.remove(1,3)

    # author_obj = models.Author.objects.filter(pk=2).first()
    # author_obj1 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.remove(author_obj,author_obj1)
    """
    remove
        括号内既可以传数字也可以传对象 并且都支持多个
    """


    # 修改
    # book_obj.authors.set([1,2])  # 括号内必须给一个可迭代对象
    # book_obj.authors.set([3])  # 括号内必须给一个可迭代对象

    # author_obj = models.Author.objects.filter(pk=2).first()
    # author_obj1 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.set([author_obj,author_obj1])  # 括号内必须给一个可迭代对象

    """
    set
        括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个
    """


    # 清空
    # 在第三张关系表中清空某个书籍与作者的绑定关系
    book_obj.authors.clear()
    """
    clear
        括号内不要加任何参数
    """

 

posted @ 2023-03-02 20:10  猿小姜  阅读(55)  评论(0编辑  收藏  举报