在使用Django/DRF时,需要关于如何处理和/或避免循环导入的架构建议吗

2024-06-03 14:21:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我想就一个我已经遇到过很多次的架构问题提出建议。 我在events.py中有一个模型事件:

# models.py
import events.serializers

class Event(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255, db_index=True)
    ...

    def save(self, *args, **kwargs):
        is_new = not self.pk
        super().save(*args, **kwargs)
        if is_new:
            self.notify_organiser_followers()

    def notify_organiser_followers(self):
        if self.organiser:
            event_data = events.serializers.BaseEventSerializer(self).data
            payload = {'title': f'New event by {self.organiser.name}',
                       'body': f'{self.organiser.name} has just created a new event: {self.name}',
                       'data': {'event': event_data}}
            send_fcm_messages(self.organiser.followers.all(), payload)

该模型有一个名为BaseEventSerializer的序列化程序。在save方法中,我使用notify_organizer_followers,并在此过程中序列化正在保存的当前事件。为此,我必须导入BaseEventSerializer

下面是events.serializers的代码的外观:

# serializers.py
import events.models

class EventTrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = events.models.EventTrack
        fields = ('id', 'name', 'color')


class BaseEventSerializer(serializers.ModelSerializer):
    event_type = serializers.CharField(source='get_event_type_display')
    locations = serializers.SerializerMethodField()

如您所见,serializers.py必须导入模型才能在ModelSerializer中使用它们。在这一步中,我以一个明显的循环导入结束

我解决这个问题的方法是在notify_organizer_followers函数中本地导入BaseEventSerializer:

def notify_organiser_followers(self):
    if self.organiser:
        from events.serializers import BaseEventSerializer

这消除了问题,但我真的希望避免这种情况,特别是因为我必须在回购协议中的多个点上进行相同的修复。我想到的另一种方法是将“常规”序列化程序和模型序列化程序分离到单独的文件中。然而,这仍然让人感觉它只是治标不治本

我想要的是关于如何避免这种情况的建议。我在导入两个使用彼此序列化程序的不同应用程序时遇到了相同的问题。例如,用户序列化他正在参加的活动,活动序列化其参与者。您将如何将这两个模型解耦?似乎模型关系常常迫使我进入这些情况,避免循环导入变得非常困难

如果您有任何更大的Django/DRF Github项目来展示如何避免这种情况,我也将不胜感激,因为一旦我的应用程序变得足够大,这个问题就会不断出现


Tags: namepy模型selfeventdata序列化models
1条回答
网友
1楼 · 发布于 2024-06-03 14:21:11

有几种不同的方法可以做到这一点,而且可能有不同的策略组合

这里我建议使用django信号和创建服务类

首先,使用django signalsModel事件之后触发特定操作。Django内置了监听器,用于在模型上发生save之类的事情时使用,您可以基于此执行不同的操作。这允许您将事件层与模型分离

单件作品: 我认为Models方法不应该执行与自身无关的操作。我认为最好创建某种通用服务作为单例,比如

EventService(): 
   def do_event_related_logic(self, event):
       ...

event_service = EventService()

您可以简单地导入event_服务,并将该类用于所有与事件相关的逻辑。在本例中,您可以在post_save事件上调用一个单例方法

相关问题 更多 >