2

我很难弄清楚这一点。我有两个自定义用户模型(例如:Buyer、Seller),它扩展了一个自定义用户模型(CustomUser),它包含所有常见字段(包括email我们需要使用哪些字段来过滤内容)并且是一个abstract模型。

现在,我们正在使用第三方电子邮件服务从/向我们的应用程序发送和接收电子邮件。第三方服务会通知我们某个事件。比如说,如果一封电子邮件被退回或失败,他们会在 url 上向我们发送一个 POST 请求callback,在验证请求后,我们会更新我们的记录并记下哪封电子邮件失败了。

我们有一个额外的电子邮件模型(SentMessage),我们在其中保存已发送的消息。这个模型看起来像这样。

class SentMessage(models.Model):
    subject = models.CharField(max_length=100)
    body = models.TextField()
    sender = models.ForeignKey(models.InternalUser)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    recipient = generic.GenericForeignKey('content_type', 'object_id')
    bounced = models.BooleanField(default=False)

如您所见,recipient上述模型中的字段是 aGenericForeignKey并且可以绑定到任何其他模型(在我们的例子中为买方或卖方)。如果消息在退回事件等中被退回,我们将在此模型中更新记录。我希望使用第三方服务提供的电子邮件地址过滤掉收件人。所以基本上流程是这样的。

--> 使用给定的电子邮件地址过滤收件人。(收件人可以是买家或卖家)--> 使用上述内容,SentMessage根据事件类型过滤退回或失败的邮件。

我被困在这里的第一点。如何过滤Buyer模型或Seller模型中存在的对象。我什至不能执行以下操作,因为CustomUser类是一个抽象类,两者都Buyer继承Seller自:

recipient = models.CustomUser.objects.get(email=bounced_email)

从给定的电子邮件地址中查找(过滤)出content_type,object_id的最佳方法是什么?recipient

4

2 回答 2

1

这是你需要去的地方https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/

首先获取 content_type 的类,然后使用 object_id 获取对象

recipient = models.CustomUser.objects.get(email='guido@example.com')
messages = SentMessage.objects.filter(content_object=recipient, email=bounced_email)
于 2013-03-25T08:19:14.703 回答
0

我倾向于同意 n3storm 的观点,即抽象模型可能不适合这种情况,但我假设您有使用它的理由。

在这种情况下,也许GenericRelation你的具体模型中的 a 可以解决问题,因为它GenericRelation充当 a 的“反向关系” GenericForeignKey。(https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation

例如,可能会起作用:

class CustomUser(models.Model):
    # ... your common fields

    class Meta:
        abstract = True

class Buyer(CustomUser):
    # ... buyer-specific fields
    sent_messages = GenericRelation(SentMessage)

class Seller(CustomUser):
    # ... seller-specific fields
    sent_messages = GenericRelation(SentMessage)


recipient_list = [x for x in Buyer.objects.filter(sent_messages=bounced_email)] + 
                 [x for x in Seller.objects.filter(sent_messages=bounced_email)]
# The above list can contain at most one element since a SentMessage will reference at most one object.

关于验证的一些评论:除非您对SentMessage.content_typeFK 进行一些验证,否则GFK引用的模型不是Buyeror Seller。这可以通过limit_choices_tocontent_typeFK 中使用来防止,尽管您必须确保调用模型实例的full_clean方法来应用验证( https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-对象)。Django Admin 正确使用来防止输入无效的 FK 值。SentMessagelimit_choices_to

另外,我认为默认情况下,GFK 不会强制object_id你引用的存在(至少从 1.4 开始,这是我正在使用的)。这意味着最终可能会出现recipient_list上面示例中的空的情况。

警告:向模型添加 GenericRelation 意味着删除该模型的实例也将级联删除与 GFK 链接的条目。在这种情况下,这意味着删除 aBuyer将删除所有SentMessage与 that 相关的内容Buyer。有关如何解决此功能/限制的更多信息,请参阅https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation 。

于 2013-08-20T19:02:52.580 回答