【Django DRF多对多使用through自定义中间表详解】

Django多对多使用through自定义中间表详解

多对多中间表详解

我们都知道对于ManyToMany字段,Django采用的是第三张中间表的方式。通过这第三张表,来关联ManyToMany的双方。下面我们根据一个具体的例子,详细解说中间表的使用。

默认中间表

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name


class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person)

    def __str__(self):
        return self.name

在Group模型中,通过members字段,以ManyToMany方式与Person模型建立了关系。
让我们来看看,中间表是个什么样子的:
在这里插入图片描述
首先有一列id,这是Django默认添加的,没什么好说的。然后是Group和Person的id列,这是默认情况下,Django关联两张表的方式。如果你要设置关联的列,可以使用to_field参数。

可见在中间表中,并不是将两张表的数据都保存在一起,而是通过id的关联进行映射。

通过through自定义中间表

一般情况,普通的多对多已经够用,无需自己创建第三张关系表。但是某些情况可能更复杂一点,比如如果你想保存某个人加入某个分组的时间呢?想保存进组的原因呢?

Django提供了一个through参数,用于指定中间模型,你可以将类似进组时间,邀请原因等其他字段放在这个中间模型内。例子如下:

modle:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name


class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name


class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()  # 进组时间
    invite_reason = models.CharField(max_length=64)  # 邀请原因

view:

class PersonViews(ModelViewSet):

    queryset = Person.objects.filter()
    serializer_class = PersonSerializers


class GroupViews(ModelViewSet):

    queryset = Group.objects.filter()
    serializer_class = GroupSerializers


class MembershipViews(ModelViewSet):

    queryset = Membership.objects.filter()
    serializer_class = MembershipSerializers

serializer:

from .models import Person, Group, Membership


class MembershipSerializers(serializers.ModelSerializer):

    class Meta:
        model = Membership
        fields = '__all__'


class PersonSerializers(serializers.ModelSerializer):

    class Meta:
        model = Person
        fields = '__all__'


class GroupSerializers(serializers.ModelSerializer):

    def to_representation(self, instance):
        representation = super(GroupSerializers, self).to_representation(instance)
        representation['members'] = []
        for i in PersonSerializers(instance.members, many=True).data:
            reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i['id'])).data['invite_reason']
            i['invite_reason'] = reason
            representation['members'].append(i)
        return representation

    class Meta:
        model = Group
        fields = '__all__'

从Membership角度,他是建立量到两个模型(Group,Person)的多对1关系,Django在启动时,会自动在其关联的模型上建立"[model]_set"的属性,就想常规的多对一关系一样——实际上他就是常规的多对一关系,只不过Person让其充当另外的角色罢了。

在这里插入图片描述
reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i[‘id’])).data[‘invite_reason’]
instance.membership_set.get(group=instance.id, person=i[‘id’]) group和person联合查出邀请原因
person和group模型上membership对象的默认名称都将为membership_set.所以通过instance.membership_set.get()可以查看group下的所有关系

person下的所有membership:

    # def to_representation(self, instance):
    #     representation = super(PersonSerializers, self).to_representation(instance)
    #     representation['reason'] = MembershipSerializers(instance.membership_set, many=True).data
    #     return representation

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django DRFDjango Rest Framework)是一个用于构建RESTful API的强大框架。当需要处理多文件上传时,可以通过以下步骤使用Django DRF来实现: 1. 首先,需要在Django项目的settings.py文件中进行一些配置。设置MEDIA_ROOT为文件上传的目录,例如: ``` MEDIA_ROOT = os.path.join(BASE_DIR, 'media') ``` 同时,设置MEDIA_URL为文件访问的URL路径,例如: ``` MEDIA_URL = '/media/' ``` 2. 创建一个serializer.py文件来定义文件上传的序列化器。在序列化器中,使用FileField或者ImageField来处理文件的上传。例如: ```python from rest_framework import serializers class FileSerializer(serializers.Serializer): file = serializers.FileField() ``` 3. 在视图中使用上面定义的序列化器来处理文件上传。例如: ```python from rest_framework.views import APIView from rest_framework.response import Response from .serializers import FileSerializer class FileUploadView(APIView): def post(self, request, format=None): serializer = FileSerializer(data=request.data) if serializer.is_valid(): file = serializer.validated_data['file'] # 在这里可以对文件进行进一步的处理,例如保存到本地或者数据库中 return Response({'message': '文件上传成功'}) else: return Response(serializer.errors, status=400) ``` 4. 在项目的urls.py文件中设置URL路由,将文件上传的URL与上述视图相关联。例如: ```python from django.urls import path from .views import FileUploadView urlpatterns = [ path('upload/', FileUploadView.as_view(), name='file_upload'), ] ``` 至此,通过以上步骤可以实现Django DRF多文件上传功能。当客户端发送POST请求,将文件作为单数据发送到上传的URL中,Django DRF将会使用序列化器来处理文件上传,并返回相应的响应结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值