私は食材のリストを含むデータベースを持っています。私はこのテーブルの重複したエントリを避けたいと思います。私は2つの理由のためにunique
キーワードを使用したくない: Djangoでエントリの一意性をカスタマイズする
- 私の一意性制約もう少し洗練された単なる私は例外を発生させたくない
=
- とき、既存の成分よりもモデルを作成する代わりに、そのモデルを返すだけで、
Ingredient(ingredient_name='tomato')
と書くことができ、そのすべてをtry
節にカプセル化するのではなく、私の一日を続けることができます。これにより、レシピテーブルに食材をすぐに追加することができます。
一つの解決策は、create_ingredient
のようなラッパー関数を持っているだけであるが、私はそれが特にエレガントであることを見つけていない、より具体的に、それは単にラッパーを使用するのを忘れるラインの下のいくつかの他の開発者に堅牢ではありません。代わりに、私はpre_initとpost_initシグナルで遊んでいます。
は、ここで私がこれまで持っているものです。
class Ingredient(models.Model):
ingredient_name = models.CharField(max_length=200)
recipes = models.ManyToManyField(Recipe,related_name='ingredients')
def __str__(self):
return self.ingredient_name
class Name(models.Model):
main_name = models.CharField(max_length=200, default=None)
equivalent_name = models.CharField(max_length=200, primary_key=True, default=None)
def _add_ingredient(sender, args, **kwargs):
if 'ingredient_name' not in kwargs['kwargs'] :
return
kwargs['kwargs']['ingredient_name'] = kwargs['kwargs']['ingredient_name'].lower()
# check if equivalent name exists, make this one the main one otherwise
try:
kwargs['kwargs']['ingredient_name'] = Name.objects.filter(
equivalent_name=kwargs['kwargs']['ingredient_name']
)[0].main_name
except IndexError:
name = Name(main_name=kwargs['kwargs']['ingredient_name'],
equivalent_name=kwargs['kwargs']['ingredient_name'])
name.save()
pre_init.connect(_add_ingredient, Ingredient)
これまでのところは良いです。これは実際に動作し、モデルが初期化される前に必要に応じてingredient_name
を置き換えます。今私がしたいのは、問題の成分がすでに存在しているかどうかを調べ、イニシャライザがそれを返すようにすることです。私はこれを行うにはpost_init
と遊ぶ必要があると思うが、私は作成されている特定のインスタンスを変更する方法を知らない。私がコメントしてきたようにinstance = ...
が実際にinstance
を変更しないので、私はこれが動作するように期待していない、それだけで変数名を再割り当て
def _finalize_ingredient(sender, instance, **kwargs):
try:
# doesn't work because of python's "pass arguments in python's super unique way of doing things" thing
instance = Ingredient.objects.filter(ingredient_name=instance.ingredient_name)[0]
except IndexError:
pass
post_init.connect(_finalize_ingredient, Ingredient)
(あなたが実行しようついでに場合:ここで私はそれによって何を意味するかです私はこれが間違っていないことを知っているので、私は理解しても気にしない、あらゆる種類の恐ろしいことが起こります。だから私は実際にこれをやりますか?私は本当にラッパー関数がここで最もクリーンなオプションではないことを願っています。私はOOPの大ファンであり、これはOOPの解決策を望んでいる(私が言ったように、長期的にはラッパーよりはるかに頑強で安全だと思う)。
レシピに私にはadd_ingredient
メソッドを追加することができますが、このすべてを私のために行うことができますが、Ingredient
クラスにこのすべてを含めるというのが本当に好きです。どんな状況でも。私はまた、post_init
メソッドを使用して、特定の状況で作成されたオブジェクトを完全にオーバーライドすることができるかどうかについて知りたいと思っています。私はIngredient
テーブルにName
テーブルを接続します私のName
クラスでForeignKey
エントリを持っていない理由ところで
は、あなたのいくつかは不思議に思われるかもしれません。結局のところ、私のチェックは私の_add_ingredient
メソッドで本質的に達成されているものではありませんか?その理由の1つは、私がこれを行うと、私はここで解決しようとしているのと同じ問題に終わるということです:私はレシピにそれを加えるために素早く原料を作りたいと思ったら、単にName
オブジェクトIngredient
オブジェクトを作成したときに、既に使用されているmain_name
に対応する場合は例外が発生します(必要なオブジェクトを単に返すのではなく)。