[英]Django model polymorphic related field
我試圖刪除我的Django模型中的重復代碼。 正如您在下面的代碼中看到的, send_salary_notification
和send_pension_notifications
之間的唯一區別是,一個使用相關的字段jurisdiction
,另一個使用agency
。 我如何重構代碼,以便根據record_type
設置管轄區/代理商一次?
我嘗試創建一個類變量作為record_type
,並在第一個函數中設置變量cls.record_type = record_type
,然后這個:
agencies_changed.append(subscription.record_type)
但是這給出了一個錯誤,即record_type不是有效的實例。
這是我的代碼:
class Subscriber(models.Model):
email = models.EmailField(null=False, unique=True)
activation_key = models.CharField(max_length=64)
key_expires = models.DateTimeField(default=get_key_expiration)
verified = models.BooleanField(default=False)
@classmethod
def send_notifications(cls, record_type, slugs):
"""
Sends notifications for all subscribers.
"""
subscribers = cls.objects.all()
for subscriber in subscribers:
if record_type == 'salary':
subscriber.send_salary_notifications(slugs, record_type)
elif record_type == 'pension':
subscriber.send_pension_notifications(slugs, record_type)
def send_salary_notifications(self, slugs, record_type):
matching_subscriptions = self.get_matching_salary_subscriptions(slugs)
agencies_changed = []
if not matching_subscriptions:
return None
for subscription in matching_subscriptions:
agencies_changed.append(subscription.jurisdiction)
self.update_salary_last_year_sent(subscription)
message = self.build_notification_message(agencies_changed, record_type)
self.send_notification_email(message)
def send_pension_notifications(self, slugs, record_type):
matching_subscriptions = self.get_matching_pension_subscriptions(slugs)
agencies_changed = []
if not matching_subscriptions:
return None
for subscription in matching_subscriptions:
agencies_changed.append(subscription.agency)
self.update_pension_last_year_sent(subscription)
message = self.build_notification_message(agencies_changed, record_type)
self.send_notification_email(message)
class SalarySubscription(models.Model):
subscriber = models.ForeignKey('subscriptions.Subscriber', related_name='salary_subscriptions')
jurisdiction = models.ForeignKey('jurisdiction.Jurisdiction')
last_year_sent = models.PositiveSmallIntegerField(null=True)
class PensionSubscription(models.Model):
subscriber = models.ForeignKey('subscriptions.Subscriber', related_name='pension_subscriptions')
agency = models.ForeignKey('pensions.Agency')
last_year_sent = models.PositiveSmallIntegerField(null=True)
假設您不想更改get_matching_pension_subscriptions
, get_matching_salary_subscriptions
, update_salary_last_year_sent
和update_pension_last_year_sent
方法,則可以將代碼重構為以下內容。 您可以使用getattr
builtin動態定義單個通知方法並獲取相關屬性,具體取決於record_type
。 可能有其他重構解決方案更適合您的代碼庫,但看到您發布此解決方案的代碼片段非常合理。
class Subscriber(models.Model):
@classmethod
def send_notifications(cls, record_type, slugs):
"""
Sends notifications for all subscribers.
"""
subscribers = cls.objects.all()
for subscriber in subscribers:
subscriber._send_notification(record_type, slugs)
def _send_notification(self, record_type, slugs):
matching_subscriptions = getattr(self, 'get_matching_{}_subscriptions'.format(record_type))(slugs)
if not matching_subscriptions:
return None
agencies_changed = []
agency_attribute = {
'salary': 'jurisdiction',
'pension': 'agency'
}[record_type]
for subscription in matching_subscriptions:
agencies_changed.append(getattr(subscription, agency_attribute))
getattr(self, 'update_{}_last_year_sent'.format(record_type))(subscription)
message = self.build_notification_message(agencies_changed, record_type)
self.send_notification_email(message)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.