设计模型:在django中使用单身模型进行搜索

时间:2017-07-24 08:17:32

标签: python django inheritance design-patterns django-models

我有一个模型TranslationService,它有一些字段和方法应该被每个新服务覆盖。我有三个服务:Google,Azure,Bing,这是系统中唯一的服务(我们只有一个Google服务和一个Azure服务等)。我需要执行这样的操作:TranslationService.objects.filter(service_name=service_name)

但是如果我使TranslationService抽象,我不能迭代抽象类,因为它不是在DB中创建的。如果我进行继承,我应该在代码中实现重写方法的逻辑,然后通过控制台创建GoogleService。这是唯一的方法,或者我可以通过控制台减少创建对象。

如何设计我的模型以便在translation_services中执行搜索?

class TranslationService(models.Model):
 created_at = models.DateTimeField(auto_now_add=True)
 updated_at = models.DateTimeField(auto_now=True)
 service_name = models.CharField(max_length=40)
 base_url = models.CharField(max_length=255)
 api_version = models.FloatField()

 def get_step_translation(self, pk, lang, lesson):
    pass

 def create_step_translation(self, pk, lang, type):
    pass

class GoogleTranslator(TranslationService):
 base_url = "https://google.com"
 service_name = "Google"
 api_version = 1.5

 def get_step_translation(self, pk, lang, lesson, **kwargs):
  ... some logic
 def create_step_translation(self, pk, lang, type):
  ... some logic

1 个答案:

答案 0 :(得分:1)

我认为模型继承是错误的方法。模型类表示数据库表,并且您的对象都存在于同一个表中,因此它们应该是相同的模型。

你可以在if语句中包含每个翻译方法的逻辑,但我理解为什么你想要抽象出来。那么您委派所有操作的单独服务类怎么样?您可以覆盖__getattr__来设置服务并委派方法。

class GoogleTranslation(object):
    def __init__(self, obj):
        self.obj = obj
    def get_step_translation(self, pk, lang, lesson):
        print('google, {}, {}, {}'.format(pk, lang, lesson))
        ... logic goes here...
    def create_step_translation(self, pk, lang, type):
        ...

class TranslationService(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    service_name = models.CharField(max_length=40)
    base_url = models.CharField(max_length=255)
    api_version = models.FloatField()

    services = {
         'google': GoogleTranslation,
         'bing': BingTranslation,
    }

    @property
    def service(self):
        if not hasattr(self, '_service'):
            # create a new Service object and pass it this model instance
            self._service = self.services[self.service_name](self)
        return self._service

    def __getattr__(self, name):
        if name == '_service':
            raise AttributeError   # the service hasn't been instantiated yet
        # delegate all unknown lookups to the service object
        return getattr(self.service, name)

现在,您可以通过gs = TranslationService.objects.get(service_name='google')获取Google实例并执行gs.get_step_translation(1, '2', '3')或其他任何操作,并且该方法调用将委托给GoogleTranslation实例。