2017-10-26 2 views
0

私はをメモするチェンジログを作成しようとしています。1)日付時刻オブジェクトが作成/更新されました。2)オブジェクト自体(文字列)
本来、.save()が呼び出されたときの特定の時刻にオブジェクトの値と共に日付と時刻を「スナップショット」します。ここで古いデータに依存する「変更履歴」を作成する際にモデルを整理するにはどうすればよいですか?

は、私が表示しようとしてる例のchangelogである:上記

Oct. 24, 2017, 11:22 a.m 
"preference: bots", "preference: chocolate sundaes" 

Oct. 19, 2017, 12:04 p.m 
"preference: dogs", "preference: potatoes" 

Sep. 03, 2017, 01:22 a.m 
"preference: cats", "preference: cheese" 

例は、3つの更新プログラムの単一Changelogを示しており、単一Changelogは、単一Profileオブジェクトに属します。

私は現在の日時またはオブジェクトの値を照会していませんが、以前のすべての日時と値は表示するデータベースに保持されていなければなりません。したがって、Changelogオブジェクト全体だけでなく、日付時刻CLDateのオブジェクトと、私が呼び出したオブジェクト:CLPreferenceのモデルを作成する必要があると考えました。ここProfile含め
は、すべてのモデルの4です:

class Profile(models.Model): 
    user = models.OneToOneField(settings.AUTH_USER_MODEL, 
           on_delete=models.CASCADE, 
           null=True, blank=True) 
    main_preference = models.CharField(max_length=54, blank=True, null=True) 
    secondary_preference = models.CharField(max_length=54, blank=True, null=True) 

    timestamp = models.DateTimeField(auto_now=True) 

    def __str__(self): 
     return self.user.username 

    def get_preferences(self): 
     preferences = self.main_preference, self.secondary_preference 
     return preferences 


class Changelog(models.Model): 
    owner = models.OneToOneField(Profile) 
    date_set = models.CharField(max_length=200) 
    preference_set = models.CharField(max_length=200) 

    def __str__(self): 
     return self.owner 


class CLDate(models.Model): 
    date_owner = models.ForeignKey(Changelog, on_delete=models.CASCADE, related_name='dates') 
    date = models.CharField(max_length=100) 

    def __str__(self): 
     return self.date_owner 


class CLPreference(models.Model): 
    preference_owner = models.ForeignKey(Changelog, on_delete=models.CASCADE, related_name='preferences') 
    preference = models.CharField(max_length=200) 

    def __str__(self): 
     return self.preference_owner 

コードの説明:私は、これは良い方法であるかどうかわからないんだけど、データテーブルを描画した後、これを可能にするように見えました。最終的に、forループと逆の関係を使って、CLDateCLPreferenceデータセットにアクセスして値をリストしました。

def profile_post_save_receiver(sender, instance, created, *args, **kwargs): 
    if instance: 
     o, created = Changelog.objects.get_or_create(owner=instance) 

     d = CLDate(date_owner=instance, date=instance.timestamp) 
     d.save() 
     p = CLPreference(preference=instance.get_preferences()) 
     p.save() 
post_save.connect(profile_post_save_receiver, sender=Profile) 

コード説明:これは--the Changelogオブジェクトが原因CLDateに作成することができませんすぐにif後に失敗した限り、実際に物事をインスタンス化し、私はポストセーブ信号を使用して、それを試みた

CLSkillはデータベースに存在しません。今のところ私はProfileモデルのメソッドget_preferences()を使用してモデルCLPreferenceに保存しようとしましたが、インスタンスtimestampを使用して現在の時刻がsave()になっています。

私はこれを引き出し、さまざまな方法でそれを試してみましたが、これを克服しているようには見えません。モデルの構造、コントローラのアスペクト、またはそれを動作させる可能性のあるものについてアドバイスしてください。私はどんな方法にも開放的です。

答えて

0

これを実現するには、ContentTypeGenericForeignKeyという概念を活用することができます。これを使用することの利点は、他のモデルのチェンジログを1つのテーブルにまとめることができる単一のチェンジログ・テーブルを作成することになります。

from django.contrib.contenttypes.fields import GenericForeignKey 
from django.contrib.contenttypes.models import ContentType 

class GenericChangelog(models.Model): 

    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey('content_type', 'object_id') 
    created_on = models.DateTimeField(auto_now_add=True) 
    data = models.TextField() 

ProfileテーブルにコンテンツタイプIDが割り当てられています。クエリ中に、そのIDを使用してGenericChangelog.objects.filter(object_id=99999, content_type_id=1).order_by('-created_on')のようなクエリを実行します(プロファイルコンテンツタイプIDが1であると仮定します)。これにより、オブジェクトの履歴が降順で返されます。

この変更ログは、標準のポストセーブレシーバーから入力することができます。コンテンツタイプIDを検索して設定するには、ContentType.objects.get_for_model(instance) を使用することもできます。また、モデルオブジェクトからクイックJSONを生成するショートカットは、from django.forms.models import model_to_dict

から入手可能な関数 model_to_dictを使用することです。
関連する問題