![](/img/trans.png)
[英]Using a filter to limit a GenericForeignKey model list with django-polymorphic
[英]Django Model Design using GenericForeignKey
我有一個Scheme模型,只能分配2個獎勵,一個用於方案成員,另一個用於他們的朋友。
以下是我為此設計模型的方法,但現在我開始質疑設計,Scheme和獎勵的鏈接是否不正確? 我是否應該在抽象獎勵上反過來呢?
方案:
class Scheme(models.Model):
name = models.CharField(max_length=60)
participant_reward_content_type = models.ForeignKey(ContentType,
editable=False,
related_name='%(app_label)s_%(class)s_as_participant',
null=True, blank=True
)
participant_reward_object_id = models.PositiveIntegerField(null=True, blank=True)
participant_reward = generic.GenericForeignKey('participant_reward_content_type', 'participant_reward_object_id')
friend_reward_content_type = models.ForeignKey(ContentType,
editable=False,
related_name='%(app_label)s_%(class)s_as_friends',
null=True, blank=True
)
friend_reward_object_id = models.PositiveIntegerField(null=True, blank=True)
friend_reward = generic.GenericForeignKey('friend_reward_content_type', 'friend_reward_object_id')
獎勵:
class AbstractReward(models.Model):
"""
Abstract reward common information shared for all rewards.
"""
description = models.CharField(max_length="150")
active = models.BooleanField(default=True)
#scheme = models.ForeignKey(Scheme, null=True,)
class Meta:
abstract = True
class SingleVoucherReward(AbstractReward):
"""
Single-use coupons are coupon codes that can only be used once
"""
pass
class Meta:
app_label = 'schemes'
class MultiVoucherReward(AbstractReward):
"""
A multi-use coupon code is a coupon code that can be used unlimited times.
"""
code = models.CharField(max_length=200)
expiry = models.DateTimeField(null=True)
class Meta:
app_label = 'schemes'
class CustomReward(AbstractReward):
"""
A reward class used when it can't be handled or they would like to
handle reward fulfillment themselves.
"""
pass
class Meta:
app_label = 'schemes'
我建議保持它非常簡單 - http://en.wikipedia.org/wiki/KISS_principle
鑒於3種類型獎勵的數據定義相似,我會完全失去繼承,只需給它一個類型選擇:
class Reward(models.Model):
SINGLE = 'Single'
MULTI = 'Multi'
CUSTOM = 'Custom'
TYPE_CHOICES = (
(SINGLE, 'Single'),
(MULTI, 'Multi'),
(CUSTOM, 'Custom'),
)
description = models.CharField(max_length="150")
active = models.BooleanField(default=True)
type = models.CharField(max_length=10, choices=TYPE_CHOICES, default=SINGLE)
code = models.CharField(max_length=200, blank=True)
expiry = models.DateTimeField(null=True)
Django的兩個獨立 - 這是如何在Django中處理事物的一個很好的參考 - 也推薦這種方法。
這也意味着您不需要GenericForeignKey並且可以使用簡單的外鍵,從而大大降低了復雜性:
class Scheme(models.Model):
name = models.CharField(max_length=60)
participant_reward = models.ForeignKey('Reward', null=True, blank=True)
friend_reward = models.ForeignKey('Rewards', null=True, blank=True)
像Django管理員和ModelForms這樣的內置工具將采用這種方法開箱即用。
有些人可能不喜歡TYPE_CHOICES的冗長,但維護起來非常簡單明了。
我也意識到你最終可能會在Reward類上使用必須修改不同類型行為的方法,例如:
if self.type = CUSTOM:
pass
但這又是非常簡單的維護。 如果代碼開始真正分歧,您可以使用代理模型 。
有些人可能會爭辯說這不是'Pythonic',但我們並沒有在這里處理純python類,除了Python的Zen之外,它還是第三個原則:
簡單比復雜更好。
您可以使您的AbstractReward
不那么抽象(並將其重命名為BaseReward
),然后將ForeignKey
重命名為它,並在某種方法中獲得實際的獎勵類型和對象。 您需要提出額外的請求,但我認為它與GenericForeignKey
相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.