• 课程版块,外键相关


    外键关联的优缺点

    优点:插入修改数据时,会自动查询关联表,如果数据不合法,就不能修改,保证数据不会错乱,不会出现脏数据

    缺点:每次校验会消耗资源,数据量大会很慢,其实可以通过程序控制脏数据不被录入。

    公司一般建立外键,但是不会有约束。

    on_delete参数

    CASCADE:这就是默认的选项,级联删除,你无需显性指定它。
    PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。
    SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。
    SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。
    SET(): 放一个函数内存地址,关联字段删除时,执行这个函数。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    class BookModel(models.Model):
        """
        图书
        """
        book_name = models.CharField(max_length=100, verbose_name='书名')
        # 表示外键关联到作者表,当作者表删除了该条数据,图书表中不删除,仅仅是把外键置空
        author = models.ForeignKey(AuthModel, null=True, blank=True, on_delete=models.SET_NULL)
        price = models.FloatField(verbose_name='价格')
        create_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ManyToMany参数(through,db_constraint)

    class Book(models.Model):
        name=models.CharField(max_length=20)
        authors=models.ManyToMany('Author',through='Score')
    
    
    class Author(models.Model):
        name=models.CharField(max_length=20)
    
    
    class Score(models.Model):
        book=models.ForeignKey('Book')
        author=models.ForeignKey('Author')
        socre=models.IntegerField()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    如果ManyToMany没有指定through参数,django会自动创建第三张表,通过authors.add()、.remove()、.set()、.clear()对第三张关系表进行操作。但是第三张表的扩展性很差,不能给第三张表添加字段。

    而如果不写ManyToMany字段,那么我们可以通过Score来执行一些操作,但是此时book和author表已经没有直接的联系了,查询起来很繁琐。

    在ManyToMany中指定through参数(authors=models.ManyToMany('Author',through='Score')),既有了扩展性,也方便使用ORM的跨表查询。

    db_constraint

    db_constraint=False,这个就是保留跨表查询的便利(双下划线跨表查询),但是不用约束字段了,一般公司都用false,这样就省的报错,因为没有了约束(Field字段对象,既约束,又建立表与表之间的关系)

    如果使用两个表之间存在关联,首先db_constraint=False 把关联切断,但保留连表查询的功能,其次要设置null=True, blank=True,注意on_delete=models.SET_NULL 一定要置空,这样删了不会影响其他关联的表。

    related_name
    反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’。

    related_query_name
    反向查询操作时,使用的连接前缀,用于替换表名。

    Meta类主要字段如:
    db_table:ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。
    index_together: 联合索引。
    unique_together:联合唯一索引。
    ordering:指定默认按什么字段排序。只有设置了该属性,我们查询到的结果才可以被reverse()。

    一 课程相关接口

    课程分类接口

    serializers.py

    class CourseCategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = CourseCategory
            fields = ['id', 'name']
    
    • 1
    • 2
    • 3
    • 4

    views.py

    # 课程分类接口
    class CourseCategoryView(GenericViewSet, ListMixinView):
        queryset = CourseCategory.objects.filter(is_delete=False, is_show=True).order_by('orders')
        serializer_class = CourseCategorySerializer
    
    • 1
    • 2
    • 3
    • 4

    课程接口

    serializers.py

    class CourseSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Course
            fields = [
                'id',
                'name',
                'course_img',
                'price',
                'students',
                'pub_sections',
                'sections',
                'brief',
                'attachment_path',
                'period',
                'course_type_name',
                'level_name',
                'status_name',
                'section_list',
                'teacher_info',
            ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    views.py

    # 所有课程接口
    class CourseView(GenericViewSet, ListMixinView, RetrieveModelMixin):
        queryset = Course.objects.filter(is_delete=False, is_show=True).order_by('orders')
        serializer_class = CourseSerializer
    
    • 1
    • 2
    • 3
    • 4

    models.py

    class Course(BaseModel):
        """课程"""
        course_type = (
            (0, '付费'),
            (1, 'VIP专享'),
            (2, '学位课程')
        )
        level_choices = (
            (0, '初级'),
            (1, '中级'),
            (2, '高级'),
        )
        status_choices = (
            (0, '上线'),
            (1, '下线'),
            (2, '预上线'),
        )
        name = models.CharField(max_length=128, verbose_name="课程名称")
        # blank 后台管理录入可以为空,null 存到数据库字段可以为空
        course_img = models.ImageField(upload_to="courses", max_length=255, verbose_name="封面图片", blank=True, null=True)
        course_type = models.SmallIntegerField(choices=course_type, default=0, verbose_name="付费类型")
        # TextField 大文本, 存html
        brief = models.TextField(max_length=2048, verbose_name="详情介绍", null=True, blank=True)
        level = models.SmallIntegerField(choices=level_choices, default=0, verbose_name="难度等级")
        pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True)
        period = models.IntegerField(verbose_name="建议学习周期(day)", default=7)
        attachment_path = models.FileField(upload_to="attachment", max_length=128, verbose_name="课件路径", blank=True,
                                           null=True)
        status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="课程状态")
        # 优化字段
        students = models.IntegerField(verbose_name="学习人数", default=0)
        sections = models.IntegerField(verbose_name="总课时数量", default=0)
        pub_sections = models.IntegerField(verbose_name="课时更新数量", default=0)
        price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价", default=0)
    
        teacher = models.ForeignKey("Teacher", on_delete=models.DO_NOTHING, null=True, blank=True, verbose_name="授课老师",
                                    db_constraint=False)
        course_category = models.ForeignKey("CourseCategory", on_delete=models.SET_NULL, db_constraint=False, null=True,
                                            blank=True, verbose_name="课程分类")
    
        class Meta:
            db_table = "luffy_course"
            verbose_name = "课程"
            verbose_name_plural = "课程"
    
        def __str__(self):
            return "%s" % self.name
    
        @property
        def course_type_name(self):
            return self.get_course_type_display()
    
        @property
        def level_name(self):
            return self.get_level_display()
    
        @property
        def status_name(self):
            return self.get_status_display()
    
        @property
        def teacher_info(self):
            from django.conf import settings
            image = settings.HOST_URL + '/media/' + self.teacher.image.name
            return {
                'id': self.id,
                'name': self.teacher.name,
                'role': self.teacher.role_name,
                'title': self.teacher.title,
                'signature': self.teacher.signature,
                'image': image,
                'brief': self.teacher.brief,
            }
    
    	@property
        def section_list(self):
            res_list = []
            # 先查出课程章节 课程 =》课程章节 反向
            chapters_qs = self.coursechapters.all()
            for chapter_obj in chapters_qs:
                # chapter_obj是章节对象 章节 =》课时 反向
                sections_qs = chapter_obj.coursesections.all()
                for sections_obj in sections_qs:
                    res_list.append({
                        'id': sections_obj.id,
                        'name': sections_obj.name,
                        'section_type_name': sections_obj.section_type_name,
                        'section_link': sections_obj.section_link,
                        'duration': sections_obj.duration,
                        'free_trail': sections_obj.free_trail,
                    })
                    if len(res_list) > 3:
                        return res_list
                return res_list
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    二 定制序列化字段的三种方式

    方式一:在序列化中定义一个字段,SerializerMethodField的对象,在写一个get_字段的方法,这个方法返回什么,序列化类就序列化什么。

    CourseSerializer序列化类中

    teacher = serializers.SerializerMethodField()
    
    
    def get_teacher(self, obj):
        image = settings.HOST_URL + '/media/' + obj.teacher.image.name
        return {
            'id': obj.id
            'name': obj.teacher.name,
            'role': obj.teacher.role_name,
            'title': obj.teacher.title,
            'signature': obj.teacher.signature,
            'image': image,
            'brief': obj.teacher.brief,
        }
    
    
    section_list = serializers.SerializerMethodField()
    
    
    def get_section_list(self, course_obj):
        res_list = []
    
        # 先查出课程章节 课程 =》课程章节 反向
        chapters_qs = course_obj.coursechapters.all()
        for chapter_obj in chapters_qs:
            # chapter_obj是章节对象 章节 =》课时 反向
            sections_qs = chapter_obj.coursesections.all()
            for sections_obj in sections_qs:
                res_list.append({
                    'id': sections_obj.id
                    'name': sections_obj.name,
                    'section_type_name': sections_obj.section_type_name,
                    'section_link': sections_obj.section_link,
                    'duration': sections_obj.duration,
                    'free_trail': sections_obj.free_trail,
                })
                if len(res_list) > 3:
                    return res_list
            return res_list
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    方式二:在模型类中写函数,函数返回什么,序列化类就能序列化什么。

    models.py

    # 获取choice字段真正的值
    @property
    def course_type_name(self):
        return self.get_course_type_display()
    
    
    @property
    def level_name(self):
        return self.get_level_display()
    
    
    @property
    def status_name(self):
        return self.get_status_display()
    
    
    @property
    def teacher_info(self):
        from django.conf import settings
        image = settings.HOST_URL + '/media/' + self.teacher.image.name
        return {
            'id': self.id,
            'name': self.teacher.name,
            'role': self.teacher.role_name,
            'title': self.teacher.title,
            'signature': self.teacher.signature,
            'image': image,
            'brief': self.teacher.brief,
        }
    
    @property
    def section_list(self):
        res_list = []
        # 先查出课程章节 课程 =》课程章节 反向
        chapters_qs = self.coursechapters.all()
        for chapter_obj in chapters_qs:
            # chapter_obj是章节对象 章节 =》课时 反向
            sections_qs = chapter_obj.coursesections.all()
            for sections_obj in sections_qs:
                res_list.append({
                    'id': sections_obj.id,
                    'name': sections_obj.name,
                    'section_type_name': sections_obj.section_type_name,
                    'section_link': sections_obj.section_link,
                    'duration': sections_obj.duration,
                    'free_trail': sections_obj.free_trail,
                })
                if len(res_list) > 3:
                    return res_list
            return res_list
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    方式三:返回哪个模型表的字段,就重写一个这个模型表的序列化类,再在查询的序列化类中指定返回字段为模型表的序列化类即可。

    class TeacherSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Teacher
            fields = ['id', 'name', 'role_name', 'title', 'signature', 'image', 'brief']
    
    
    class CourseSerializer(serializers.ModelSerializer):
        teacher = TeacherSerializer()
    
        class Meta:
            model = Course
            fields = [
                'id',
                'name',
                'course_img',
                'price',
                'students',
                'pub_sections',
                'sections',
                'brief',
                'attachment_path',
                'period',
                'course_type_name',
                'level_name',
                'status_name',
                'teacher',
                'section_list',
            ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    三 章节相关接口

    查询所有章节接口带按课程id过滤功能
    serializers.py

    class CourseChapterSerializer(serializers.ModelSerializer):
        class Meta:
            model = CourseChapter
            fields = [
                'id',
                'name',
                'chapter',
                'summary',
                'pub_date',
                'course_info',
            ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    views.py

    # 所有章节接口
    class CourseChapterView(GenericViewSet, ListMixinView, RetrieveModelMixin):
        queryset = CourseChapter.objects.filter(is_delete=False, is_show=True).order_by('orders')
        serializer_class = CourseChapterSerializer
        filter_backends = [DjangoFilterBackend]
        filterset_fields = ['course']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    存储对象

    公司内部存储:fastdfs

    https://zhuanlan.zhihu.com/p/372286804
    
    • 1

    MinIO

    -部署完:http://docs.minio.org.cn/docs/master/minio-docker-quickstart-guide
    -web管理页面:类似于七牛云
    -python的sdk上传
    
    • 1
    • 2
    • 3
  • 相关阅读:
    ElasticSearch ES 安装 常见错误 Kibana安装 设置 权限 密码
    golang中移除切片索引位置的元素
    【Java面试题】List如何一边遍历,一边删除?
    Python Flask
    计算机网络学习笔记(五):运输层(待更新)
    【Linux】 vi / vim 使用
    nginx基础使用二————动静分离、UR Rewrite和防盗链
    成对连接点云分割
    离子液体[C7MIm]BF4/1-庚基-3-甲基咪唑四氟硼酸盐
    淘宝商品详情页视频接口(视频参数,sku属性参数,销量参数等页面上的数据均可以采集,支持高并发请求)
  • 原文地址:https://blog.csdn.net/weixin_68531269/article/details/127905539