python - django模型多态相关领域
问题描述
我正在尝试删除我的 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
内置动态获取相关属性,具体取决于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)
推荐阅读
- c# - 如何让所有视图都可以访问共享的 ProgressCircle 控件?
- azure-resource-manager - 子资源中的正确依赖分配似乎不起作用
- ios - UITableViewCell - 将背景设置为渐变以删除(可滑动操作) - Swift 4.2
- c++ - 使用 boost strand 和 std::mutex
- angular - ag-grid cellrenderer:将html标签添加到单元格但不在模板中,而是作为函数的返回值
- sql - T SQL向XML的根节点添加多个新属性
- javascript - 对象搜索键值并删除其中的第一个和最后一个字符
- curl - 重定向后的 cURL PUT
- javascript - 如何等待 http 请求完成?Javascript
- wordpress - 为什么 Wordpress 创建的图像缩略图(文件大小)比原始图像大?