2016-07-09 3 views
-1

Djangoで混乱しているのは、モデルのフィールドの仕組みです。モデルでdjangosフィールドのインスタンスが動作する方法

これらをクラス変数として定義します。

ので、このようなクラス:

class Foo: 
    avar = "something here" 

そして、あなたは2つのインスタンスを作成した場合。

f1 = Foo() 
f2 = Foo() 

そして、あなたが何か他のものであることをAVARを設定し、これはFooの両方のインスタンスに影響を与えます。だから、djangoはインスタンス間のモデルフィールド値をどのように正確に保つのでしょうか?単純に基本クラス変数を使用してテーブルを作成した後、それぞれのインスタンスの正しいフィールド値を返すようにモデル/テーブルのデータベースをクエリしますか?

モデルを__init__/__new__と言うまで、メタクラスレベルで作成を延期するようなことをして、フィールドの一意のインスタンスを作成しますか?

amodel = AModel.objects.get(*)のようなものDjangoがデータベースにヒットして、おそらくモデルのクラスのインスタンスを返すことがわかりました。フィールドの値が入力されているので、amodel.fieldにアクセスできました。値正しく。これは理にかなっていますが、私はこの仕事の内部がどのように理解されているかわかりません。

+1

:あなたは、インスタンスの変数を削除すると、値が戻って(現在の)クラス変数の値に戻ります。 2つの別々のモデルインスタンスを作成しました。それらは別々のプロパティを持つ別々のオブジェクトであり、保存する場合はデータベース内の別の行です。 – solarissmoke

+0

'models.Model'内部の仕組みを知りたければ' path/to/site-packages/django/db/models/base.py'のコードを 'class Model'で調べることができます。 – allcaps

+0

@solarissmoke OPが持つものは、* instance *属性ではなく* class *属性です。オブジェクトは文字列なので、実際には関係ありません。つまり、 'avar'に代入すると、class属性を変更する代わりにローカル変数に名前が再バインドされます。しかし、 'avar'が何か変更可能であった場合、これは重要な違いです。だから、fluffy_muffin: 'avar'の設定は両方のオブジェクトに影響するとは思いません。 'Foo.avar'を設定しない限り、なぜあなたはそれをしますか? –

答えて

1

Djangoはmetaclassを使用してすべてのフィールドを収集し、Model._metaに収集します。クラスが作成された後、フィールドはモデルクラス自体には含まれていません:

class Foo(models.Model): 
    bar = models.CharField(max_length=255) 

>>> Foo.bar 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    Foo.bar 
AttributeError: type object 'Foo' has no attribute 'bar' 

いくつかのフィールドタイプ(例えばForeignKey)クラス属性になる記述を、使用していますが、これはフィールド自体ではありません。

モデルがインスタンス化される

__init__loop throughすべて self._metaのフィールド、とは(あなたが何のフィールドのデフォルト値を提供しない通常 None場合)インスタンスにデフォルト値を割り当てます。これにより、各フィールドに値が存在し、その値がインスタンス変数であり、任意のPythonオブジェクトであることが保証されます。

すべてのモデル方法では、Foo._metaの情報を使用して、どの属性をフィールドとして扱い、通常の属性であるかを判断します。

インスタンスのクラス変数をオーバーライドすると、実際にはインスタンス変数によってクラス変数がシャドウされることにも注意してください。クラス自体の変数を変更すると、インスタンス変数を持たないインスタンスにも値が変更されます。それはあなたがここに求めているものは明らかではありません

>>> class Foo(object): 
...  bar = 'test' 
... 
>>> f1 = Foo() 
>>> f2 = Foo() 
>>> f1.bar = 'shadowed' 
>>> Foo.bar = 'changed' 
>>> f1.bar 
'shadowed' 
>>> f2.bar 
'changed' 
>>> del f1.bar 
>>> f1.bar 
'changed' 
0

ここではいくつかのことが起こっています。まず、あなたがやっているのは、ほかのPythonオブジェクトと同じようにFooオブジェクトに文字列を作成することだけです。それをデータベースのフィールドにしたい場合は、モデルの型を使用する必要があります。あなたは、モデルにいくつかの変更を加えて変更を行いたい場合は後で

from django.db import models 

class Foo(models.Model): 
    avar = models.CharField(max_length=255) 

のようなものは、その後、データベースのレコードを更新するために、save()メソッドを呼び出します。

f1.avar = "Something New" 
f1.save() 
+0

avarは単なるプレースホルダでした。私は、通常のクラス変数とdjangoが潜在的にそれらを処理する方法との間の問題を強調しようとしていました。あなたの答えは実際に私の質問をさらに強調してくれると思います。 'f1.avar'を「Something New」に設定しましたが、' f2'を保存すると言うと 'f2'の' avar'を「Something New」に設定するだけです。あるいは、理論的には、少なくとも質問のコードがどのように機能するのかというだけです。したがって、私の混乱/フィールドインスタンスのDjangoのクラス変数がどのように働くかについての質問。 –

1

通常のクラス変数は、クラスのプロパティです。データベースには格納されません(model fieldsのみ)。あなたの場合、avarはモデルフィールドではありません。単純なPythonクラス変数です。

Fooのインスタンスでクラス変数を変更すると、そのインスタンスにのみ影響します。他のすべてのインスタンスは影響を受けません。証明:

class Foo: 
    avar = 'Something' 

a = Foo() 
b = Foo() 

a.avar = 'Something else' 

print a.avar 
> 'Something else' 

print b.avar 
> 'Something' 

aavarを変更するbにそれを変更しないこと。 a.avarの変更された値は、a自体が存在する限り存在します。このプロパティはデータベースには格納されません。データベースから新しいオブジェクトをロードすると、そのクラスの既定値はavarになります。

+0

それでは、クラス変数がどのように働いていたのか、私は完全に間違っていました。これは理にかなっています。 –

+0

この回答はクラス変数*の仕組みを説明していますが、オリジナルの質問には答えません。* Djangoフィールドインスタンスはモデルでどのように動作しますか? [その他の回答](http://stackoverflow.com/questions/38278141/how-do-djangos-field-instances-work-in-models#answer-38280621)を参照してください。 – allcaps

関連する問題