合并两个具有共享ID的Django模型到一个单独的视图集。

huangapple go评论47阅读模式
英文:

Combine two django models with shared ids into a single viewset

问题

我有两个独立应用中的两个Django模型,它们使用来自外部身份验证服务的相同用户ID:

app1/models.py 中:

class App1User(models.Model):

    user_id = models.UUIDField(unique=True)
    app1_field = models.BooleanField()

app2/models.py 中:

class App2User(models.Model):

    user_id = models.UUIDField(unique=True)
    app2_field = models.BooleanField()

我想要创建一个合并的视图集,使它看起来这两个模型像是一个单一的模型,其列表响应如下:

[
    {
        'user_id': ...,
        'app1_field': ...,
        'app2_field': ...
    },
    ...
]

如果我使用这个视图集创建或更新数据,它应该将数据保存到这两个模型中。

英文:

I have two django models in two independent apps, who use the same user ids from an external authentication service:

In app1/models.py:

class App1User(models.Model):

    user_id = models.UUIDField(unique=True)
    app1_field = models.BooleanField()

In app2/models.py:

class App2User(models.Model):

    user_id = models.UUIDField(unique=True)
    app2_field = models.BooleanField()

I would like to have a combined viewset that can make it seem like these two are a single model with a list response as follows:

[
	{
		'user_id': ...,
		'app1_field': ...,
		'app2_field': ...
	},
	...
]

If I create or update with this viewset, it should save the data to each of the two models.

答案1

得分: 0

创建一个合并视图集,用于处理 App1User 和 App2User 模型,您可以按照以下步骤进行操作:

  1. 为合并模型创建一个序列化器。在您的主应用程序中,创建一个 serializers.py 文件,并定义以下序列化器:
from rest_framework import serializers
from app1.models import App1User
from app2.models import App2User

class App1UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = App1User
        fields = ('user_id', 'app1_field')

class App2UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = App2User
        fields = ('user_id', 'app2_field')

class CombinedUserSerializer(serializers.Serializer):
    user_id = serializers.UUIDField()
    app1_field = serializers.BooleanField()
    app2_field = serializers.BooleanField()

    def create(self, validated_data):
        app1_data = {'user_id': validated_data['user_id'], 'app1_field': validated_data['app1_field']}
        app2_data = {'user_id': validated_data['user_id'], 'app2_field': validated_data['app2_field']}
        app1_serializer = App1UserSerializer(data=app1_data)
        app2_serializer = App2UserSerializer(data=app2_data)
        if app1_serializer.is valid() and app2_serializer.is_valid():
            app1_serializer.save()
            app2_serializer.save()
        return validated_data

    def update(self, instance, validated_data):
        app1_instance = App1User.objects.get(user_id=validated_data['user_id'])
        app2_instance = App2User.objects.get(user_id=validated_data['user_id'])
        app1_serializer = App1UserSerializer(app1_instance, data={'app1_field': validated_data['app1_field']})
        app2_serializer = App2UserSerializer(app2_instance, data={'app2_field': validated_data['app2_field']})
        if app1_serializer.is_valid() and app2_serializer.is_valid():
            app1_serializer.save()
            app2_serializer.save()
        return validated_data

这个序列化器定义了合并模型的结构,并使用 App1UserSerializer 和 App2UserSerializer 来处理每个模型的字段。

  1. 创建一个合并模型的视图集。在您的主应用程序中,创建一个 viewsets.py 文件,并定义以下视图集:
from rest_framework import viewsets
from app1.models import App1User
from app2.models import App2User
from .serializers import CombinedUserSerializer

class CombinedUserViewSet(viewsets.ModelViewSet):
    serializer_class = CombinedUserSerializer

    def get_queryset(self):
        app1_users = App1User.objects.all()
        app2_users = App2User.objects.all()
        combined_users = []
        for app1_user in app1_users:
            app2_user = app2_users.filter(user_id=app1_user.user_id).first()
            if app2_user:
                combined_user = {
                    'user_id': app1_user.user_id,
                    'app1_field': app1_user.app1_field,
                    'app2_field': app2_user.app2_field
                }
                combined_users.append(combined_user)
        return combined_users

这个视图集使用 CombinedUserSerializer 来处理请求,并从 App1User 和 App2User 模型中检索数据。get_queryset() 方法检索所有的 App1User 和 App2User 实例,根据它们的 user_id 进行匹配,并创建一个合并用户列表。

  1. 在您的主应用程序的 urls.py 文件中注册视图集:
# main_app/urls.py

from django.urls import include, path
from rest_framework import routers
from .views import CombinedUserViewSet

router = routers.DefaultRouter()
router.register(r'combined-users', CombinedUserViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

这段代码设置了一个默认路由器,并将 CombinedUserViewSet 注册到端点 /combined-users/,用于访问合并模型数据。

以上解决方案是如何实现的思路,您可以根据自己的需求进行修改。如果这个思路有帮助,请将其标记为接受的解决方案。

英文:

> To create a combined viewset for App1User and App2User models, you can
> follow these steps:
>
> Create a serializer for the combined model. In your main app, create a
> serializers.py file and define the following serializer:

from rest_framework import serializers
from app1.models import App1User
from app2.models import App2User

class App1UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = App1User
        fields = ('user_id', 'app1_field')

class App2UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = App2User
        fields = ('user_id', 'app2_field')

class CombinedUserSerializer(serializers.Serializer):
    user_id = serializers.UUIDField()
    app1_field = serializers.BooleanField()
    app2_field = serializers.BooleanField()

def create(self, validated_data):
    app1_data = {'user_id': validated_data['user_id'], 'app1_field': validated_data['app1_field']}
    app2_data = {'user_id': validated_data['user_id'], 'app2_field': validated_data['app2_field']}
    app1_serializer = App1UserSerializer(data=app1_data)
    app2_serializer = App2UserSerializer(data=app2_data)
    if app1_serializer.is_valid() and app2_serializer.is_valid():
        app1_serializer.save()
        app2_serializer.save()
    return validated_data

def update(self, instance, validated_data):
    app1_instance = App1User.objects.get(user_id=validated_data['user_id'])
    app2_instance = App2User.objects.get(user_id=validated_data['user_id'])
    app1_serializer = App1UserSerializer(app1_instance, data={'app1_field': validated_data['app1_field']})
    app2_serializer = App2UserSerializer(app2_instance, data={'app2_field': validated_data['app2_field']})
    if app1_serializer.is_valid() and app2_serializer.is_valid():
        app1_serializer.save()
        app2_serializer.save()
    return validated_data

This serializer defines the structure of the combined model and uses App1UserSerializer and App2UserSerializer to handle the fields of each model.

> 2. Create a viewset for the combined model. In your main app, create a viewsets.py file and define the following viewset:

from rest_framework import viewsets
from app1.models import App1User
from app2.models import App2User
from .serializers import CombinedUserSerializer

class CombinedUserViewSet(viewsets.ModelViewSet):
    serializer_class = CombinedUserSerializer

    def get_queryset(self):
        app1_users = App1User.objects.all()
        app2_users = App2User.objects.all()
        combined_users = []
        for app1_user in app1_users:
            app2_user = app2_users.filter(user_id=app1_user.user_id).first()
            if app2_user:
                combined_user = {
                    'user_id': app1_user.user_id,
                    'app1_field': app1_user.app1_field,
                    'app2_field': app2_user.app2_field
                }
                combined_users.append(combined_user)
        return combined_users

This viewset uses CombinedUserSerializer to handle the requests and retrieves the data from both App1User and App2User models. The get_queryset() method retrieves all the App1User and App2User instances, matches them based on their user_id, and creates a list of combined users.

> 3. Register the viewset in your main app's urls.py file:

# main_app/urls.py

from django.urls import include, path
from rest_framework import routers
from .views import CombinedUserViewSet

router = routers.DefaultRouter()
router.register(r'combined-users', CombinedUserViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

This code sets up a default router and registers the CombinedUserViewSet with the endpoint /combined-users/, which can be used to access the combined model data.

Above solution is the idea how it can be done, you can modify according to your needs. If this idea helps, plz mark this as accept solution.

huangapple
  • 本文由 发表于 2023年2月16日 19:13:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471450.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定