我有点困难,想出这个。我有两个自定义用户模型(例如:买方,卖方),它扩展了一个自定义用户模型(CustomUser),它包含所有常用字段(包括我们需要过滤东西的email
)并且是{ {1}}模型。
现在,我们正在使用第三方电子邮件服务向/向我们的应用程序发送和接收电子邮件。第三方服务通知我们一个事件。比如说,如果电子邮件被退回或失败,他们会在abstract
网址上向我们发送POST请求,在对请求进行身份验证后,我们会更新记录并记下哪个电子邮件失败。
我们有一个额外的电子邮件模型(SentMessage),我们保存已发送的邮件。这个模型看起来像这样。
callback
如您所见,上述模型中的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
,可以绑定到任何其他模型(在我们的案例中为买方或卖方)。如果消息是在跳出事件等处进行的,我们将更新记录的模型。我希望使用第三方服务提供的电子邮件地址过滤收件人。所以基本上流程就像是。
- >使用给定的电子邮件地址过滤收件人。(收件人可以是买方或卖方)
- >使用上述内容,根据事件类型过滤掉已被退回或失败的GenericForeignKey
。
我在这里第一点陷入困境。如何过滤SentMessage
模型或Buyer
模型中存在的对象。我甚至无法执行以下操作,因为Seller
类是一个抽象类,CustomUser
和Buyer
都继承该类:
Seller
从给定的电子邮件地址中查找(过滤)recipient = models.CustomUser.objects.get(email=bounced_email)
,content_type
,object_id
的最佳方法是什么?
答案 0 :(得分: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)
答案 1 :(得分:0)
我倾向于同意n3storm一个抽象模型可能不适合这种情况,但我会假设你有理由使用它。
在这种情况下,您的具体模型中的GenericRelation
可能会起作用,因为GenericRelation
充当GenericForeignKey
的“反向关系”。 (https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation)
E.g。类似的东西可能会起作用:
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_type
FK进行了一些验证,否则不可能 GFK引用的另一个模型不是Buyer
或Seller
。这可以通过在limit_choices_to
FK中使用content_type
来防止,但您必须确保调用full_clean
模型实例的SentMessage
方法来应用验证({{3 }})。 Django Admin正确使用limit_choices_to
来阻止输入无效的FK值。
另外,我认为默认情况下,GFK不会强制存在您引用的object_id
(至少从1.4开始,这就是我正在使用的)。这意味着最终可能会出现上述示例中的recipient_list
为空的情况。
警告:向模型添加GenericRelation意味着删除该模型的实例也会级联删除GFK链接的条目。在这种情况下,这意味着删除Buyer
将删除与SentMessage
相关的所有Buyer
。有关如何解决此功能/限制的详细信息,请参阅https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects。