2009-05-14 9 views
1

これは私が書いたDjangoモデルクラスです。私がget_object_or_404をDjangoから呼び出すと、このクラスはkeyerrorを取得します(私は、get関数によって__init__に渡されるkwargsのせいでkeyerrorが発生すると考えています。面白いことに、get_object_or_404をコンソールから呼び出すとエラーにはなりません。keyerrorの中のdjangoモデルクラス__init__

私は、このコードを正しい方法(つまり、を初期化するためにリンクフィールドを設定する)がこのクラスを構築するのに不思議です。

class Link(models.Model) 

    event_type = models.IntegerField(choices=EVENT_TYPES) 
    user = models.ForeignKey(User) 
    created_on = models.DateTimeField(auto_now_add = True) 
    link = models.CharField(max_length=30) 
    isActive = models.BooleanField(default=True) 

    def _generate_link(self): 
     prelink = str(self.user.id)+str(self.event_type)+str(self.created_on) 
     m = md5.new() 
     m.update(prelink) 
     return m.hexdigest() 

    def __init__(self, *args, **kwargs): 
     self.user = kwargs['user'].pop() 
     self.event_type = kwargs['event_type'].pop() 
     self.link = self._generate_link() 
     super(Link,self).__init__(*args,**kwargs) 
+0

答えを考慮すると、initを無効にすることは問題があるようです。私はあなたの提案に従ってクラスを再構成します。みなさん、ありがとう。 (私はまだ例外がスローされるかどうかは、コンソールまたはDjangoからどこに呼び出されるかによって決まります)。 – shanyu

答えて

2

Djangoモデルクラスのために独自の__init__を書く必要はありません。私はあなたがそれなしでもっと幸せになると思います。

__init__にしたいと思われるものは、saveでおこなうことができます。

+0

と私の答えに示されているシグナリングは、 '__init__'をエミュレートすることができます – vikingosegundo

7
self.user = kwargs['user'].pop() 
self.event_type = kwargs['event_type'].pop() 

あなたは辞書からエントリを取得しようとした後、そのpopメソッドを呼び出します。あなたが削除して辞書からオブジェクトを返すようにしたい場合は、dict.pop()を呼び出す:もちろん

self.user = kwargs.pop('user') 

"user"kwargsに存在しない場合、これはKeyErrorで失敗します。あなたはポップデフォルト値を提供することをお勧めします:

self.user = kwargs.pop('user', None) 

これは、「"user"が辞書にある場合、それを削除して返しそうでない場合は、Noneを返します。」。他の二行について

self.link = self._generate_link() 
super(Link,self).__init__(*args,**kwargs) 

super().__init__()はおそらくNone、何かにlinkを設定します。私はこのような何かに、ラインを逆になります

super(Link,self).__init__(*args,**kwargs) 
self.link = self._generate_link() 

あなたはそれが既に存在するかどうかを確認するために、リンクを設定する前にテストを追加したい場合があります(if self.link is not None: ...)。そうすれば、コンストラクタに渡すリンクは上書きされません。

1

不思議なぜ、以下のコードは、正しい方法であれば、このクラスを構築するために(すなわち、リンク・フィールドを移入する__init__を使用)。

私はかつて私はメーリングリストで__init__ をオーバーロードしようとしたとき、私はそれはあなた自身の __init__でそれをオーバーロードしないことが最善ですこの答え

を得たいくつかの問題を得ました。より良い選択肢は、 カスタムメソッドを使用してpost_init信号にフックし、その方法でprocess()make_thumbnail()を呼び出します。

あなたのケースでは、post_init信号がトリックを行い、__init__を実装する必要は全くありません。 link = models.CharField(max_length=30, unique=True)のキーワードuniqueを提供することは、あまりにも、役に立つことができ

class Link(models.Model) 
    event_type = models.IntegerField(choices=EVENT_TYPES) 
    user = models.ForeignKey(User) 
    created_on = models.DateTimeField(auto_now_add = True) 
    link = models.CharField(max_length=30) 
    isActive = models.BooleanField(default=True) 

    def create_link(self): 
     prelink = str(self.user.id)+str(self.event_type)+str(self.created_on) 
     m = md5.new() 
     m.update(prelink) 
     return m.hexdigest() 

def post_link_init(sender, **kwargs): 
    kwargs['instance'].create_link() 
post_init.connect(post_link_init, sender=Link) 

>>> link = Link(event_type=1, user=aUser, created_on=datetime.now(), link='foo', isActive=True) 

: あなたはこのような何かを書くことができます。提供されていない場合、link_fieldの同じ値が複数回存在する場合にget_object_or_404は機能しません。ジャンゴ・ドキュメントで

signalsunique

2

私はあなたがすべてでここ__init__を必要としないと思います。

クラスがインスタンス化されるとき、常にlinkの値を計算します。つまり、データベースに格納されているものはすべて無視します。これが当てはまるので、なぜモデル分野を全く気にしませんか? _generate_linkのコードを使ってgetterを使って、リンクをプロパティにする方がよいでしょう。

@property 
def link(self): 
    .... 
関連する問題