精华内容
下载资源
问答
  • 主要介绍了django一对多模型以及如何在前端实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Django 一对多 多对多 正/反序列化

    万次阅读 2019-12-25 19:02:09
    Django orm 一对多,多对多 正/反序列化 器 Django 框架操作数据库 用到的是 ORM 思想,什么是 ORM 呢? Object Relational Mapping 对象关系映射,说白了 就是 操作数据库的 语句 和 Python 乃至 Django 的不太一样...

    Django orm 一对多,多对多 正/反序列化 器

    Django 框架操作数据库 用到的是 ORM 思想,什么是 ORM 呢?
    Object Relational Mapping 对象关系映射,说白了 就是 操作数据库的 语句 和 Python 乃至 Django 的不太一样 为了 方便,面向数据库的关系更改成了 面向对象。详细点的就是,创建 实例 代替 数据库中的表,类属性就是 对应的 字段了。
    接下来 执行一些简单的操作。

    # models.py
    
    # 教师表
    class Teacher(models.Model):
    	name = models.CharField(max_length=32)
    
    # 学生表
    class Student(models.Model):
    	name = models.CharField(max_length=32)
    	teacher = models.ForeignKey('Teacher', on_delete=models.CASCADE)
    
    # 课程表	
    class Course(models.Model):
    	name = models.CharField(max_length=32)
        student = models.ManyToManyField('Student')
    
    
    

    定义 视图函数:
    先添加 教师的 数据

    # 批量添加
    Teacher.objects.bulk_create(
    	name=‘老师1’, 
    	name=‘老师2’, 
    	name=‘老师3)
    
    

    添加老师对应的 学生的信息

    
    Student.objects.bulk_create(
    	(name='学生1',teacher=1),
    	(name='学生2',teacher=2),
    	(name='学生3',teacher=3)
    	)
    
    

    查询 老师 下面的学生:

    teacher = Teacher.objects.filter(id=1).first()
    
    i for i in teacher.student_set.all()
    # 也可以用 relate_name
    i for i in teacher.teacher_student.all()
    
    

    查询 学生 上面的老师:

    student = Stuednt.objects.filter(id=1).first()
    student.teacher.all()
    # teacher 是外键字段
    
    

    (多对多)课程添加学生:

    course = Course.objects.filter(id=1).first()
    student= Student.objects.filter(id=1).first()
    course.student.add(student)
    # 将课程 id 是 1 的课程和 id 为 1 的学生进行关联
    
    

    (多对多)学生添加课程:

    
    student = Student.objects.filter(id=1).first()
    course = Course.objects.filter(id=1).first()
    student.course_set.add(course)
    
    

    (多对多)查询学生对应的所有课程:

    student = Student.objects.filter(id=1).first()
    student.course_set.all()
    
    

    (多对多)课程对应的所有学生:

    
    course = Course.objects.filter(id=1).first()
    course.student.all()
    

    通过课程删除学生的

    
        # 获取课程
        course = Course.objects.filter(id=3).first()
        # 获取学生
        student = Student.objects.filter(id=2).first()
    
        course.stu.remove(student)
    
    

    通过学生删除课程的关系

    
        # 获取课程
        course = Course.objects.filter(id=6).first()
        # 获取学生
        student = Student.objects.filter(id=4).first()
    
        student.course_set.remove(course)
    
    

    序列化器

    序列化器的 Serializers 和 ModelSerializer 不是定死的 谁正谁反都可以。

    from rest_framework import serializers
    from rest_framework.response import Response 
    from . import models
    
    

    序列化器 是 rest_framework 里面的一个方法 库 随你怎么定义 先学会怎么用

    # settings.py
    INSTALL_APP = [
    	'rest_framework',
    	]
    
    

    借用之前创建 好的表。
    因为之前 做好数据了 我们先用序列化吧

    class TeacherSerializer(serializers.ModelSerializer):
    	class Meta:
    		model: models.Teacher
    		fields = '__all__' # ['id', 'name', '列表'] ('id','name', '元祖') 这几种方法都可以
    		# exclude 领域外
    
    # views.py		
    class Teacher_list(APIView):
    	def get(request):
    		teacher = models.Teacher.objects.all()
    		t = TeacherSerializer(instance=teacher, many=True)
    		return Respomse({
    			'code': 200,
    			'teacher_list': t.data
    		})
    
    
    

    这样数据就发送到前台了。
    然后 是 学生的 序列化
    (一对多)

    
    class StudentSerializer(serializers.Modelserializer):
    	teacher = serializers.CharField(source='teacher.name')
    	# teacher = TeacherSerializer()
    	class Meta:
    		model = models.Student
    		fields = ['name', 'id', 'teacher']
    
    # views.py
    class Student_list(APIView):
    	def get(request):
    		student = models.Student.objects.filter(id=1).first()
    		s = StudentSerializer(instance=student)
    		return Response({
    			'code': 200,
    			'student_list': s.data
    			})
    			
    
    

    多对多的序列化
    课程下面的学生
    (在课程表下面是拥有 那个 ManyToMany 虚拟字段)

    # 类似于 上一个 序列化 因为 多对多的本质就是由一对多
    class CourseSerializer(serializers.Modelserializer):
    	student = serializers.CharField(source='student.name')
    	# student = StudentSerializer()
    	class Meta:
    		model = models.Student
    		fields = ['name', 'id', 'student']
    
    # views.py
    class Course_list(APIView):
    	def get(request):
    		course = models.Course.objects.filter(id=1).first()
    		c = CourseSerializer(instance=course)
    		return Response({
    			'code': 200,
    			'student_list': c.data
    			})
    
    

    无虚拟字段
    学生下面的课程

    class CourseModelSerializer(serializers.ModelSerializer)
    	class Meta:
    		model = model.Course
    		fields = '__all__'
    
    # views.py		
    class StudentSerializer(serializers.Serializer):
    	name = serializers.CharField(max_length=32)
    	teacher = serializers.CharField(source='teacher.name')
    	# many = True 重点
    	course_set = CourseModelSerializer(many=True)
    	
    
    

    直接序列化 第三张表

    # 第三章表的序列化
    
    class Course_Student_Serializer(serializers.Modelserializer):
    	course_id = CourseSerializer()
    	student_id = serializers.CharField(source='student.name')
    	# student_id = StudentSerializer()
    	class Meta:
    		model = models.Course_Student
    		fields = ['id', 'student_id', 'course_id']
    
    # views.py
    class Course_Student_list(APIView):
    	def get(request):
    		course = models.Course_Student.objects.all()
    		cs = Course_Student_Serializer(instance=course, many=True)
    		return Response({
    			'code': 200,
    			'student_list': cs.data
    			})
    
    

    反序列化
    这里说明一下 反序列化的数据 更新 是根据 serializers 的底层 定义的,如果参数 传入的是 data 那么就创建, 如果是 instance 和 data 就更新。

    class TeacherUNSerializer(serializers.Serializer):
    	name = serializers.CharField()
    	def create(self, data):
    		return models.Teacher.objects.create(
    			**data
    			)
    
    # views.py
    class Teacher_list(APIView):
    	def post(self, request):
    		data  = request.data.copy()
    		teacher = TeacherUNSerializer(data=data)
    		if teacher.is_valid():
    			teacher.save()
    		print(teacher.errors)
    		return Response({
    			'code': 200
    			})
    		
    
    

    一对多的反序列化

    
    class StudentUNSerializer(serializers.Serializer):
    	name = serializers.CharField()
    	# teacher = TeacherUNSerializer()
    	teacher_id = serializers.IntegerField()
    	def create(self, data):
    		return models.Student.objects.create(
    			**data
    			)
    	def update(self, instance, data)
    		return instance.update(**data)
    
    # views.py
    class Student_list(APIView):
    	def post:
    	# 此时 传过来的数据 就携带着 student 的外键
    		student = request.data.copy()
    		s = StudentUNSerializer(data=data)
    		if s.is_valid():
    			s.save()
    		print(s.errors)
    		return Response({
    			'code': 200
    			})
    
    

    多对多 反序列化 这个就有点麻烦了
    这里 着重的说一点,多对多就是 两个 或 多个 一对多。在 一对多的时候 我们都是要有一个数据的 就是这个主表 一 那么多就是新添加的了,那两个一对多 就是说 创建的连接的两张表就是 那个 一,第三张表就是记录连接的多。
    所以说 两张连接表是要有 数据的。

    # 假设一张表(学生表)有数据 然后同时添加 两张表
    class Course_Student_UNSerializer(serializers.Serializer):
    	name = serializers.CharField()
    	# 因为传递过来的数据是字符 所以这里也用 字符类型
    	student_ids = serializers.CharField(max_length=255, write_only=True)
    	def create(self, data):
    		student_ids = eval(data['student_ids'])
    		# 先确定 有 id 的学生
    		student = models.student.objects.filter(
    			id__in = student_ids
    			)
    		del data['student_ids']    # 删除多余的字段
    		# 删除了 学生 剩下的就都是课程的了
    		c = models.Course.objects.create(
    			**data
    	 		)
    	 	# 从 课程的 ManyToMany字段 添加 
    	 	c.student.add(*student)
    	 	# 最后返回的是 c 什么意思? 就是说 上面 两个结果 都会被 返回 入 第三张连接表
    	 	return c
    
    # views.py
    class Course_Student_list(APIView):
        def post(self, request):
           # name (新添加的课程名)
           # [1,2] -> 学生的ID们
    		data = request.data.copy()
            cs = Course_Student_UNSerializer(data=data)
            if cs.is_valid():
                cs.save()
            return Response({
           		 "code": 1
           		})
    
    
    展开全文
  • Django 一对多关系(Foreign Key)

    千次阅读 2019-04-25 15:53:23
    我们使用Foreign Key 在model中来实现这种一对多关系。 from django.db import models # 记者 class Reporter(models.Model): # 名字 first_name = models.CharField(max_length=30) last_name = models....

    我们使用Foreign Key 在model中来实现这种一对多关系。

    from django.db import models
    
    # 记者
    class Reporter(models.Model):
    	# 名字
        first_name = models.CharField(max_length=30)
        last_name = models.CharField(max_length=30)
        # email信息
        email = models.EmailField()
    	# 重写了print出来的信息
        def __str__(self):
            return "%s %s" % (self.first_name, self.last_name)
    
    class Article(models.Model):
    	# 一篇文章,里面包含标题,发布时间,发布者。
        headline = models.CharField(max_length=100)
        pub_date = models.DateField()
        reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
    	# 重写了print出来的信息
        def __str__(self):
            return self.headline
    	# 排序信息:通过标题来排序
        class Meta:
            ordering = ('headline',)
    

    创建记者

    >>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
    >>> r.save()
    
    >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
    >>> r2.save()
    

    创建文章

    >>> from datetime import date
    >>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
    >>> a.save()
    
    >>> a.reporter.id
    1
    
    >>> a.reporter
    <Reporter: John Smith>
    

    你必须保存了记者后才能创建文章。
    文章和记者得到了关联。

    >>> r = a.reporter
    

    通过记者对象去创建文章

    >>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29))
    >>> new_article
    <Article: John's second story>
    >>> new_article.reporter
    <Reporter: John Smith>
    >>> new_article.reporter.id
    1
    

    创建一篇文章

    >>> new_article2 = Article.objects.create(headline="Paul's story", pub_date=date(2006, 1, 17), reporter=r)
    >>> new_article2.reporter
    <Reporter: John Smith>
    >>> new_article2.reporter.id
    1
    >>> r.article_set.all()
    <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
    
    >>> r2.article_set.add(new_article2)
    >>> new_article2.reporter.id
    2
    >>> new_article2.reporter
    

    添加错误的类型会产生错误:

    >>> r.article_set.add(r2)
    Traceback (most recent call last):
    ...
    TypeError: 'Article' instance expected, got <Reporter: Paul Jones>
    
    >>> r.article_set.all()
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    >>> r2.article_set.all()
    <QuerySet [<Article: Paul's story>]>
    
    >>> r.article_set.count()
    2
    
    >>> r2.article_set.count()
    1
    

    一系列操作后,文章从r1 移动到了r2 之后。

    相关的管理器也支持字段查找。API会根据您的需要自动跟踪关系。使用双下划线分隔关系。这可以工作到你想要的深度。是没有限制的。例如:
    过滤器查询:

    >>> r.article_set.filter(headline__startswith='This')
    <QuerySet [<Article: This is a test>]>
    
    # Find all Articles for any Reporter whose first name is "John".
    >>> Article.objects.filter(reporter__first_name='John')
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    

    and 查询:

    >>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith')
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    

    可以传递多种值

    >>> Article.objects.filter(reporter__pk=1)
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    >>> Article.objects.filter(reporter=1)
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    >>> Article.objects.filter(reporter=r)
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    
    >>> Article.objects.filter(reporter__in=[1,2]).distinct()
    <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
    >>> Article.objects.filter(reporter__in=[r,r2]).distinct()
    <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
    

    您还可以使用queryset来代替实例的文本列表:

    >>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct()
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    

    反方向查找:

    >>> Reporter.objects.filter(article__pk=1)
    <QuerySet [<Reporter: John Smith>]>
    >>> Reporter.objects.filter(article=1)
    <QuerySet [<Reporter: John Smith>]>
    >>> Reporter.objects.filter(article=a)
    <QuerySet [<Reporter: John Smith>]>
    
    >>> Reporter.objects.filter(article__headline__startswith='This')
    <QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]>
    >>> Reporter.objects.filter(article__headline__startswith='This').distinct()
    <QuerySet [<Reporter: John Smith>]>
    

    如果你想删除一个记者,那么它的文章也会被联级删除。
    (假设外键是用django.db.models.ForeignKey定义的。on_delete设置为级联,这是默认值):

    >>> Article.objects.all()
    <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
    >>> Reporter.objects.order_by('first_name')
    <QuerySet [<Reporter: John Smith>, <Reporter: Paul Jones>]>
    >>> r2.delete()
    >>> Article.objects.all()
    <QuerySet [<Article: John's second story>, <Article: This is a test>]>
    >>> Reporter.objects.order_by('first_name')
    <QuerySet [<Reporter: John Smith>]>
    
    >>> Reporter.objects.filter(article__headline__startswith='This').delete()
    >>> Reporter.objects.all()
    <QuerySet []>
    >>> Article.objects.all()
    <QuerySet []>
    
    展开全文
  • 一对多关系: 这里定义Article和Category两个数据模型,Django会自动创建“项目名_类名”的表,Article表会创建category_id的字段,来对应Category表的id,通过id关联。这种情况下查询某篇文章对应的分类,可以直接...

    以“一篇文章只能属于一个分类;一篇文章有多个标签,一个标签也可以对应多篇文章为例”。数据模型如下:

    • 一对多关系:

    这里定义Article和Category两个数据模型,Django会自动创建“项目名_类名”的表,Article表会创建category_id的字段,来对应Category表的id,通过id关联。这种情况下查询某篇文章对应的分类,可以直接在模板中引用article.category,得到的是分类名称;但有时需要查分类id,可以通过article.category.id来访问,也可以通过article.category_id,即直接访问表的字段名。

    • 多对多关系:

    文章和标签是多对多关系,Django会额外创建一个表,表里记录是两个数据模型的id,通过id把数据模型映射形成多对多关系,当需要查询某篇文章的所有标签时,需要在文章所有标签数据集里迭代查询。

    最终在浏览器呈现查询结果

    • 在视图函数中多表查询:双下划线

    如通过标签名称查询文章:list = Article.objects.filter(tags__name=tag)

    展开全文
  • django 一对多关系操作

    千次阅读 2014-01-23 15:21:41
    这段时间用django 做程序用到了一对多的关系的操作,下面分享一些心得体会,希望对大家有帮助。 我先定义两个模型,一个是作者,一个是作者出版的书籍,算是一对多的类型。 class Person(models.Model); name =...

    转载自http://www.2cto.com/kf/201208/147935.html

    这段时间用django 做程序用到了一对多的关系的操作,下面分享一些心得体会,希望对大家有帮助。


    我先定义两个模型,一个是作者,一个是作者出版的书籍,算是一对多的类型。

    class Person(models.Model);
    name = models.CharField('作者姓名', max_length=10)
    age = models.IntegerField('作者年龄')


    class Book(models.Model):
    person = models.ForeignKey(Person, related_name='person_book')
    title = models.CharField('书籍名称', max_length=10)
    pubtime = models.DateField('出版时间')


    如果我们要查询一个作者出版了哪些书籍的话,那我们要怎么做呢?

    先查询到作者的信息

    person = Person.objects.fiter(你的条件)
    返回一个person对象

    接下来就查询person关联的所有书籍对象
    book = person.book_set.all()
    django 默认每个主表的对象都有一个是外键的属性,可以通过它来查询到所有属于主表的子表的信息。
    这个属性的名称默认是以子表的名称小写加上_set()来表示,默认返回的是一个querydict对象,你可以继续的根据情况来查询等操作。

    如果你觉得上面的定义比较麻烦的话,你也可以在定义主表的外键的时候,给这个外键定义好一个名称。要用related_name比如:

    person = models.ForeignKey(Person, related_name='person_set')
    那么上面的话:book = person.book_set.all()
    也可以用book = person.person_set.all()

    上面的是查询是通过主表来查询子表的信。

    下面我简单的说下通过子表来查询主表的信息。

    假设我要查询一本书籍所关联的作者的信息,那我可以通过下面的步骤来实现:

    假如我先得到了一个子表的对象。那我只要获取该对象关联主表的外键的熟悉,就可以得到主表的信息了。
    比如我得到一个book对象,然后我想得到book对象的主表person的信息的话:
    p = book.person
    我个人感觉person有点像指针,存储着person主表对象的地址,呵呵!不过python没有指针这个概念,这是我觉的更好理解。



    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 76,829
精华内容 30,731
关键字:

django一对多