2

私はこれを理解するのに少し苦労しています。私は 2 つのカスタム ユーザー モデル (たとえば、Buyer、Seller) を持っています。これは、すべての共通フィールド (emailフィルターに必要なものを使用するものを含む) を保持し、モデルである単一のカスタム ユーザー モデル (CustomUser) を拡張しabstractます。

現在、サードパーティの電子メール サービスを使用して、アプリケーションとの間で電子メール メッセージを送受信しています。サードパーティ サービスは、イベントについて通知します。たとえば、メールがバウンスまたは失敗した場合、彼らはcallbackURL で POST リクエストを送信し、リクエストを認証した後、記録を更新し、どのメールが失敗したかを記録します。

送信されたメッセージを保存する追加の電子メール モデル (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のとおり、上記のモデルのフィールドは であり、GenericForeignKey他のモデル (この場合は買い手または売り手) にバインドできます。これは、バウンス イベントなどでメッセージがバウンスされた場合にレコードを更新するモデルです。サード パーティ サービスから提供された電子メール アドレスを使用して受信者を除外しようとしています。ということで、基本的にはこんな流れになります。

SentMessage--> 特定の電子メール アドレスを使用して受信者を除外します (受信者は購入者または販売者のいずれかになります) --> 上記を使用して、イベントの種類に応じてバウンスまたは失敗したものをフィルター処理します。

ここで最初のポイントで立ち往生しています。Buyerモデルまたはモデルに存在するオブジェクトをフィルターするにはどうすればよいですかSellerCustomUserクラスは抽象クラスであり、両方BuyerからSeller継承されるため、次のこともできません。

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

特定の電子メール アドレスから 、content_typeobject_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ため、おそらく具体的なモデルの でうまくいくでしょう。( https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation )GenericRelationGenericForeignKey

たとえば、次のようなものが機能する可能性があります。

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 がまたは以外の別のモデルを参照することは不可能ではありません。これはFK で使用することで防ぐことができますが、モデル インスタンスのメソッドを呼び出して検証を適用する必要があります ( https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-オブジェクト)。Django 管理者は を適切に使用して、無効な FK 値の入力を防ぎます。BuyerSellerlimit_choices_tocontent_typefull_cleanSentMessagelimit_choices_to

また、デフォルトでは、GFK は参照している の存在を強制しないと思いobject_idます (少なくとも 1.4 では、これを使用しています)。recipient_listこれは、上記の例の が空になる可能性があることを意味します。

警告: GenericRelation をモデルに追加すると、そのモデルのインスタンスを削除すると、GFK にリンクされたエントリもカスケード削除されます。この場合、 を削除すると、その に関連Buyerするすべての が削除されることを意味します。この機能/制限を回避する方法の詳細については、 https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelationを参照してください。SentMessageBuyer

于 2013-08-20T19:02:52.580 に答える