课程版块,外键相关

外键关联的优缺点

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

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

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

on_delete参数

CASCADE:这就是默认的选项,级联删除,你无需显性指定它。
PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。
SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。
SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。
SET(): 放一个函数内存地址,关联字段删除时,执行这个函数。
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='添加时间')

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()

如果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']

views.py

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

课程接口

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',
        ]

views.py

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

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

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

方式一:在序列化中定义一个字段,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

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

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

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

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',
        ]

三 章节相关接口

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

class CourseChapterSerializer(serializers.ModelSerializer):
    class Meta:
        model = CourseChapter
        fields = [
            'id',
            'name',
            'chapter',
            'summary',
            'pub_date',
            'course_info',
        ]

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']

你可能感兴趣的:(django,python,后端)