2017-10-29 6 views
0

Djangoのdumpdataを使用してデータを保存し、loaddataを使用して再読み込みしています。私は自然なキーも使用しています。私のモデルは次のようになります。Djangoのロードデータは、どのフィールドがナチュラルキーを作るのかを知っていますか?

class LinkManager(models.Manager): 
    def get_by_natural_key(self, url): 
     return self.get(url=url) 

class Link(models.Model): 
    objects = LinkManager() 
    title = models.CharField(max_length=200) 
    url = models.URLField() 

    def natural_key(self): 
     return (self.url,) 

私はエクスポートしたデータを再インポートした場合、Djangoはオブジェクトがすでに存在していることを認識し、複製を作成しません。タイトルを変更すると、オブジェクトが正しく更新されます。しかし、URLを変更すると、正しく新しいオブジェクトとして扱われますが、urlというマークは忘れてしまいました!私の意図はどうやって推測されますか?

私のurlフィールドが自然なキーであることをdjangoはどのように知っていますか? get_natural_fields機能はありません。 Djangoはフィールドを取得するには、インスタンスの代わりにクラスnatural_keyを呼び出すことができますが、それは本当に脆いようだ:

>>> [f.field_name for f in Link.natural_key(Link)] 
['url'] 

私はこれを知ってほしい理由は、私は私自身の特別な輸入を書いていますということである(交換します私はloaddataを使用しています)、それぞれのモデルのナチュラルキー(または「識別する」フィールド)をハードコーディングすることなくナチュラルキーを利用したいと思います。現在、私はそれによってオブジェクトが独自のフィールドだ「識別」 - 私が行います

obj, created = Model.objects.update_or_create(**identifying, defaults=other) 

が、Djangoはそれが違ったフィールドを「特定」が選択しているように見えます。

答えて

0

私はそれを見つけたと思う。 Djangoはget_by_natural_keyを呼び出すだけではなく、最初にnatural_keyを呼び出します。それがモデルのインスタンスを持っていない場合、それはどうしますか?

これは単に、データベースによってサポートされていないインスタンスをコンストラクタ(つまり、oh!)から作成します。Model(**data)django.core.serializers.basebuild_instanceを参照してください。次に、新しく作成されたオブジェクトのnatural_keyを呼び出し、即座にget_by_natural_keyを呼び出して、データベースに存在するオブジェクトに属するpkを取得します。このようにして、Djangoは自然キーが依存するフィールドを知る必要はなく、単にデータから取得する方法を知る必要があります。取得したインスタンスでsave()を呼び出すことができます。データベースにある場合は、pkが更新され、更新されない場合は新しい行が作成されます。 build_instance機能(ジャンゴ1.11.2)の

出典:

def build_instance(Model, data, db): 
    """ 
    Build a model instance. 

    If the model instance doesn't have a primary key and the model supports 
    natural keys, try to retrieve it from the database. 
    """ 
    obj = Model(**data) 
    if (obj.pk is None and hasattr(Model, 'natural_key') and 
      hasattr(Model._default_manager, 'get_by_natural_key')): 
     natural_key = obj.natural_key() 
     try: 
      obj.pk = Model._default_manager.db_manager(db).get_by_natural_key(*natural_key).pk 
     except Model.DoesNotExist: 
      pass 
    return obj 
関連する問題