Django数据库主表从表

一对多

models.py

from django.db import models

# Create your models here.

# 数据库:一对多。它指的是两个表之间的关系,一指的是主表中的一条数据,多指的是从表中的多条数据。
# 两个表:
# 班级表(1班,2班,3班)
# 学生表(张三-1班, 李四-1班, 王五-1班,赵六-2班,麻子-3班,小明-2班)
# 这两个表:班级表就是主表,因为班级表的一条数据(比如1班)对应了学生表的多条数据(张三-1班, 李四-1班, 王五-1班),所以学生表是从表。

class Classes(models.Model):
    """
    这是班级表,是主表;
    """
    c_name = models.CharField(max_length=20)

    class Meta:
        db_table = 'classes'

class Student(models.Model):
    """
    这是从表,学生表;
    主表中的一条数据可以对应从表中的多条数据;
    从表中的一条数据只能对应主表中的一条数据;
    """
    s_name = models.CharField(max_length=20)

    # 如何在从表中关联主表的ID?
    # ForeignKey()外键,在Student表中,关联外部表Classes的主键,所以称为外键。
    # on_delete:必须设置。表示从表数据所关联的主表数据被删除以后,从表应该怎么办。
    # 1. CASCADE:如果主表数据删除,从表对应的数据也全部删除;
    # 比如:张三、李四、王五关联的都是1班,如果1班这条数据被删除了,那么,对应的张三、李四、王五也全部删除;
    # 2. SET_NULL:如果主表数据删除,从表数据保留,但是这种外键的关联关系classes_id设置为NULL。

    # 从表关联两个主表的外键。
    # related_name指定外键的关联名称,这个名称是用于将来查询数据使用的。只在主表查从表时会用到。
    classes_one = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name='cls_one')
    classes_two = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name='cls_two')


    class Meta:
        db_table = 'student'

 

views.py

from django.shortcuts import render
from django.views.generic import View
from .models import Classes, Student

# 通用视图类的用法:
# 1. 主要作用还是用于配置url路由,只不过形式和视图函数的写法不一样,但是功能是一样的;视图函数区分GET和POST主要是通过request.method,而通用视图将GET和POST请求封装成了类中的两个方法;

class Home(View):
    def get(self, request, id):
        print('------', id)
        """
        self和request是固定的两个参数,这两个参数后面如果还有参数,那就是url传递的参数;
        :param request:
        :return:
        """
        return render(request, 'index.html')

    def post(self, request, id):
        print('=======', id)
        a = request.POST.get('a')
        b = request.POST.get('b')

        return render(request, 'index.html', {'result': int(a)+int(b)})

class DataHandler(View):
    def get(self, request):

        # 数据库中要先存在主表的数据,然后才能创建从表的数据。
        # c1 = Classes(c_name='1班')
        # c1.save()
        # c2 = Classes(c_name='2班')
        # c2.save()
        # c3 = Classes(c_name='3班')
        # c3.save()

        # 关联主表id:通过classes(表面)或者classes_id(核心)都可以进行绑定;
        # s1 = Student(s_name="张三", classes_one=c1, classes_two=c1)
        # s1.save()
        # s2 = Student(s_name="李四", classes_id=c1.id)
        # s2.save()
        # s3 = Student(s_name="王五", classes=c2)
        # s3.save()
        # s4 = Student(s_name="赵六", classes_id=c3.id)
        # s4.save()

        # return render(request, 'index.html')

        # 如何根据主表的一条数据查询所有从表的数据?
        c1 = Classes.objects.get(id=1)
        # 语法:主表数据.从表名称_set
        # student_set就是一个查询结果集,所有的学生数据都在里面。
        # stus = c1.student_set.all()

        # 如果从表出现,多个关联同一个主表的外键,就不能再使用student_set了,无法区分是classes_one还是classes_two。
        stus = c1.cls_two.all()

        # 如何根据从表的一条数据查询对应的一条主表的数据?
        s1 = Student.objects.get(id=1)
        # classes就是s1对象的属性,是在Student类中声明的一个属性。
        classes_name = s1.classes_two.c_name

        return render(request, 'index.html', {'stus': stus})

 

一对一

models.py

from django.db import models

# Create your models here.
# ORM数据库的一对一关系:一个表中的一条数据对应着另外一个表中的一条数据。
# 例如: 一个账户只对应着一个联系人,一个联系人只能有一个账户。身份证。

class Account(models.Model):
    """
    一个账户类
    """
    # 账户名称
    a_name = models.CharField(max_length=20)
    # 账户密码
    a_pwd = models.CharField(max_length=100)
    # 账户激活的时间
    # DateField()参数为空,这个字段的值需要自己添加。
    # auto_now=True: 当这个Account这个对象的属性被修改了,在保存的时候,这个a_register_date这个时间会自动更新为保存时间;(强调更新时间)
    # auto_now_add=True: 含义就是这个时间字段,不会随着对象的修改而更新这个时间,只在这个对象被第一次创建的时候自动填充创建的时间。以后也不会再变动了。(强调创建时间)
    # auto_created=True: 表示使用当前时间作为值,自动创建这个字段的值。默认是False。当创建对象的时候就不需要给这个字段赋值了,会自动创建。
    a_register_date = models.DateTimeField(auto_now_add=True, auto_created=True)
    a_update_date = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = 'account'


class Contact(models.Model):
    """
    一个账户的拥有人。
    """
    # 所有人的姓名
    c_name = models.CharField(max_length=20)
    # 所有人的住址
    c_address = models.TextField()
    # 所有人的联系方式
    c_phone = models.CharField(max_length=20)

    # 添加账户和所有人的一对一关系。
    # models.CASCADE:当account表中的一条数据删除时,对应的contact表中的数据也要删除。
    account = models.OneToOneField(Account, on_delete=models.CASCADE)

    class Meta:
        db_table = 'contact'

# 将models.OneToOneField写在哪一个表中,哪一个表就是从表;OneToOneField()的第一个参数就是主表;
# OneToOneField不强调位置关系,两个表中任选一个作为主表,另一个作为从表;

# 一对多:一必须是主表,多是从表,强调位置关系。

views.py

from django.shortcuts import render
from .models import Account, Contact
from datetime import datetime

def add(request):
    # 添加主表数据
    a1 = Account(a_name='1@qq.com', a_pwd='123', a_register_date=datetime.now(), a_update_date=datetime.now())
    a1.save()
    a2 = Account(a_name='2@qq.com', a_pwd='456', a_register_date=datetime.now(), a_update_date=datetime.now())
    a2.save()
    # 添加从表数据
    c1 = Contact(c_name='张三', c_address='北京', c_phone='111', account=a1)
    c1.save()
    c2 = Contact(c_name='李四', c_address='郑州', c_phone='222', account_id=a2.id)
    c2.save()

    return render(request, 'index.html', {'result': '数据添加成功'})

def select(request):
    # 根据主表的一条数据,查询从表的一条数据。也就是查询该账户的拥有人。
    account = Account.objects.get(id=2)
    contact = account.contact.c_name
    # 根据从表的一条数据,查询主表的一条数据。也就是查询这个人的账户。
    contact = Contact.objects.get(id=2)
    account = contact.account.a_name
    return render(request, 'index.html', {'data': account})


def update(request):
    account = Account.objects.get(id=1)
    account.a_pwd = '111'
    account.save()

    return render(request, 'index.html', {'result': '数据修改成功'})


def delete(request):
    Account.objects.get(id=1).delete()
    return render(request, 'index.html', {'result': '数据删除成功'})

 

多对多

models.py

from django.db import models

# Create your models here.

# 多对多:一个表中的一条数据对应另外一个表中的多条数据;另外一个表中的一条数据对应着前一个表中的多条数据;

class Publication(models.Model):
    """
    出版社(主表)
    """
    p_name = models.CharField(max_length=50)


class Article(models.Model):
    """
    文章(从表)
    """
    a_name = models.CharField(max_length=50)
    pub = models.ManyToManyField(Publication)


# 一对多:ForginKey一定要设置在从表。
# 一对一和多对多:关系可以设置在任意一个表中。

views.py

from django.shortcuts import render
from .models import *
from django.http import HttpResponse
# Create your views here.

def index(request):
    # 添加
    # 一对一和一对多:先添加主表的数据,再添加从表的数据;
    # 多对多:先分别添加两个表的数据,然后再进行关联;
    # p1 = Publication(p_name='新华出版社')
    # p1.save()
    # p2 = Publication(p_name='东方出版社')
    # p2.save()
    #
    # a1 = Article(a_name='个税改革')
    # a1.save()
    # a2 = Article(a_name='大桥通车')
    # a2.save()

    # 关联文章和出版社的关系
    # a1这个文章关联的出版社是p1和p2,意思就是p1和p2两个出版社都出版了a1这个文章。
    # a1.pub.add(p1, p2)
    # a2.pub.add(p2)

    # 查询:
    # 1-根据主表数据查询从表数据;
    # 查询 "东方出版社" 出版过的所有文章;
    p1 = Publication.objects.get(id=2)
    articles = p1.article_set.all()
    for article in articles:
        print(article.a_name)
    # 2-根据从表数据查询主表数据;
    # 查询 "个税改革" 这个文章,共有几个出版社出版;
    a1 = Article.objects.get(id=1)
    pubs = a1.pub.all()
    for p in pubs:
        print(p.p_name)

    return HttpResponse('数据添加成功')

 

posted @ 2018-11-22 16:58  陈桑啊丶  阅读(1359)  评论(0编辑  收藏  举报