Django多个对象的ForeignKey

4 投票
1 回答
4755 浏览
提问于 2025-04-17 12:55

我正在创建一个应用程序,用户可以订阅或关注网站的不同内容。

我正在建立一个表格,用来记录所有这些订阅。我的初步想法是做一个订阅表,这个表会列出所有被订阅的内容。现在我的计划是这样的:

class SubscriptionTypeCode(object):
    CITY = '1'
    REGION = '2'
    COUNTRY = '3'
    USER = '4'

SUBSCRIPTION_TYPE_CHOICES = (
    (SubscriptionTypeCode.CITY, 'City'),
    (SubscriptionTypeCode.REGION, 'Region'),
    (SubscriptionTypeCode.COUNTRY, 'Country'),
    (SubscriptionTypeCode.USER, 'User'),
)
class Subscription(models.Model):
    subscriber = models.ForeignKey(User, related_name="subscriber")
    subscription_type = models.CharField(max_length=4, choices=SUBSCRIPTION_TYPE_CHOICES)
    subscription_to_user = models.ForeignKey(User, related_name="subscription_to_user", null=True, blank=True)
    subscription_to_city = models.ForeignKey(City, null=True, blank=True)
    subscription_to_country = models.ForeignKey(Country, null=True, blank=True)
    subscription_to_region = models.ForeignKey(Region, null=True, blank=True)
    created = models.DateTimeField(db_index=True, auto_now_add=True)
    cancelled = models.DateTimeField(null=True, blank=True)

这个方法应该是可行的,但我在想这样做是否是最有效的方式。每一行都会有一个订阅者的ID,然后是类型选择,接着根据这个选择,某个订阅到的列会有一个外部对象。

这个方法是有效的,但在逻辑上需要很多if/else语句。例如:

def create_subscription(request, subscription_type, subscription_id):
    subscription = Subscription.create(
        subscriber = request.user,
        subscription_type = subscription_type,
    )
    if subscription_type == SubscriptionTypeCode.REGION:
        region = get_region(subscription_id)
        subscription.subscription_to_region = region

    elif subscription_type == SubscriptionTypeCode.CITY:
        city = get_city(subscription_id)
        subscription.subscription_to_city = city

    elif subscription_type == SubscriptionTypeCode.COUNTRY:
        country = get_country(subscription_id)
        subscription.subscription_to_country = country

    elif subscription_type == SubscriptionTypeCode.USER:
        user = get_user(subscription_id)
        subscription.subscription_to_user = user

    subscription.save()
    return subscription

你们有什么想法可以简化这个吗?或者这样做可以吗?

1 个回答

3

你可以使用通用外键(只需要一个subscription_to字段)或者模型继承(为不同的订阅类型创建Subscription的子类,这样至少能让你的代码结构更清晰)。

撰写回答