wjs521

Django 之多对多关系

1. 多对多关系

作者 <--> 书籍
1. 表结构设计
1. SQL版

-- 创建作者表

create table author(
id int primary key auto_increment,
name varchar(32) not null
);

-- 创建作者和书的关系表

create table author2book(
id int primary key auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key (author_id) references author(id) on delete cascade on update cascade,
constraint fk_book foreign key (book_id) references book(id) on delete cascade on update cascade
);

2. ORM版

1. 第一版:

自己创建第三张表

2. 第二版

让ORM帮我们创建第三张表
models.ManyToManyField()

3. 第三版

待补充...(ORM进阶操作的时候)

2. 作者的增删改查

1. 查询

# 展示作者
def author_list(request):
    # 1. 去数据库查询到所有的作者
    author_data = Author.objects.all()
    for author in author_data:
        print(author)
        # 取到每个作者出版的书籍
        # print(author.books)  # 是一个ORM提供的桥梁(工具),帮我找对应关系
        print(author.books.all())
    # 2. 在页面上展示出来
    return render(request, \'author_list.html\', {\'author_list\': author_data})

author_obj.books --> 得到的只是一个关联关系,并不能拿到数据
author_obj.books.all() --> 得到和我这个作者关联的所有书籍对象列表

2. 添加

1. add()

# 添加作者
def add_author(request):
    if request.method == \'POST\':
        # 1. 取到用户填写的信息
        new_author_name = request.POST.get(\'author_name\')
        # book_ids = request.POST.get(\'books\')  # -->这个只能取到一个值
        book_ids = request.POST.getlist(\'books\')
        # print(new_author_name)
        # print(book_ids)
        print(request.POST.getlist(\'hobby\'))
        print(\'-\' * 120)
        # 2. 添加到数据库
        # 2.1 创建新的作者
        author_obj = Author.objects.create(name=new_author_name)
        # 2.2 创建新作者和书的对应关系
        author_obj.books.add(*book_ids)  # 参数是一个一个单独的书籍id值
        # author_obj.books.set(book_ids)  # 参数是书籍id值的列表
        # 3. 跳转到作者列表页面
        return redirect(\'/author_list/\')
    # 1. 返回一个页面给用户,让用户填写作者信息
    # 2. 获取所有的书籍信息
    book_data = Book.objects.all()
    return render(request, \'add_author.html\', {\'book_list\': book_data})

 

3. 删除

# 删除作者
def delete_author(request):
    # 1. 取到要删除的作者的id值
    delete_author_id = request.GET.get(\'kangchen\')
    age = request.GET.get(\'age\')
    print(delete_author_id)
    print(age)
    # 2. 同过id找到数据,并删除
    Author.objects.filter(id=delete_author_id).delete()
    # 3. 让用户再访问作者列表页面
    return redirect(\'/author_list/\')

 

4. 编辑

# 编辑作者
def edit_author(request):
    # 1. 取到要编辑的作者的id值
    edit_author_id = request.GET.get(\'id\')
    # 2. 找到要编辑的作者对象
    edit_author_obj = Author.objects.get(id=edit_author_id)

    if request.method == \'POST\':
        # 3. 拿到编辑之后的数据
        new_author_name = request.POST.get(\'author_name\')
        new_book_ids = request.POST.getlist(\'book_ids\')
        # 4. 去数据库修改
        # 4.1 修改作者表
        edit_author_obj.name = new_author_name
        edit_author_obj.save()
        # 4.2 修改作者和书的关系表
        edit_author_obj.books.set(new_book_ids)
        # 5. 跳转到作者列表页面
        return redirect(\'/author_list/\')

    # 2.2 找到所有的书籍对象
    book_data = Book.objects.all()
    # 3. 返回一个页面
    return render(request, \'edit_author.html\', {\'author\': edit_author_obj, \'book_list\': book_data})

 

1. 模板语言中

{% if book in author.books.all %}

2. ORM编辑多对多

1. 不能直接操作第三张关系表
2. 借助ORM给提供的方法

  •   all()
  •   add(id1,id2)
  •   set([id1, id2])
  •   clear()

3. Django模板语言

1. for循环

1. forloop.last

{% if forloop.last %}
...

2. empty

{% for i in x %}
...
{% empty %}
...
{% endfor %}

4. 上传文件

form表单上传文件

views.py中

# 上传文件
def upload(request):
    if request.method == \'POST\':
        # 1. 取到用户发送的数据
        print(request.POST)
        print(request.FILES)
        file_obj = request.FILES.get(\'file_name\')
        print(file_obj.name)
        # 判断当前是否存在
        file_name = file_obj.name
        if os.path.exists(os.path.join(settings.BASE_DIR, file_name)):
            # 如果存在同名的文件
            name, suffix = file_name.split(\'.\')
            name += \'2\'
            file_name = name + \'.\' + suffix
        # 从上传文件对象里 一点一点读取数据,写到本地
        with open(file_name, \'wb\') as f:
            # 从上传文件对象里 一点一点读取数据
            for chunk in file_obj.chunks():
                f.write(chunk)
    # 1. 第一次GET请求来,应该给用户返回一个页面,让用户选择文件
    return render(request, \'upload.html\')

html文件中

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>上传文件示例</title>
</head>
<body>


<h1>上传文件</h1>
<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="test">
    <input type="file" name="file_name">
    <input type="submit">
</form>

</body>
</html>

 

分类:

技术点:

相关文章: