0

ユーザーが辞書を渡すことができるカスタム フィールドを作成しました。この辞書は、データベースに文字列として保存されます。これが私の models.py クラスの主要部分です。

class OptionsField(models.Field):
    description = 'All options'
    #__metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 2048
        kwargs['unique'] = False
        kwargs['null'] = True 
        super(OptionsField, self).__init__(*args, **kwargs) 

    def db_type(self, connection):
        return 'varchar(2048)'

    #Transforms database values to a python dictionary     
    def to_python(self, value): 
        if isinstance(value, dict):
            return value
        together = value.split(' \n')
        returnDictionary = {}
        for item in together:
            dictionaryField = item.split(' : ')
            returnDictionary[dictionaryField[0]] = dictionaryField[1]
        return returnDictionary

    #Transforms a python dictionary to database-compatible values (string)    
    def get_prep_value(self, dict): 
        databaseList = [] 
        print dict
        for key, value in dict.iteritems():
            listValue = ' : '.join([str(key), str(value)])
            databaseList.append(listValue)
        databaseList.sort()
        return ' \n'.join(databaseList) 
-------------------------------END OF CUSTOM FIELD---------------------

class MyModel(models.Model):
    options = OptionsField()

    class Meta:
        app_label = 'testingDB' 

そして私のメインの中で、私は次のことができます

dictionary = {'a':'b', 'c':'d'}
example = MyModel(options = dictionary) 
example.save() 

example.options['ZZ'] = 'z'
example.options['a'] = 'grr'

example.save()

最初の保存では、データベースに次のものが配置されます。

+----+--------+
| id | options| 
+----+--------+
|  1 | a : b  |  
|    | c : d  | 
+----+--------+

2 回目の保存では、上記が次のように変更されます。

+----+--------+
| id | options| 
+----+--------+
|  1 | a : grr|  
|    | c : d  | 
|    | ZZ : z |
+----+--------+    

このデータベースを検索するにはどうすればよいですか? 私が何かをするなら test=MyModel.objects.filter(options['a'] = 'b')

SyntaxError: Keyword can't be an expression メソッド get_prep_lookup を作成する必要があると思います。さまざまなことを試しましたが、うまくいかないようです。

ドキュメント: https://docs.djangoproject.com/en/1.4/howto/custom-model-fields/

4

2 に答える 2

2

私はそれを理解したと思います。Django のメイン プログラムで辞書を使用することを希望する他の人にとって、これは私がしなければならなかったことです。

まず、コメントを外さなければなりませんでした

__metaclass__ = models.SubfieldBase

上記の行により、to_pythonメソッドが自動的に呼び出されるようになります。(完全には理解できませんが、添付したドキュメント リンクで説明されています)。

その後get_prep_lookup、Field クラス内でメソッドを完成させる必要がありました。これは検索用です。これは私がしたすべてです:

def get_prep_lookup(self, lookup_type, value):
    #value is a dictionary, eg: {'a': 'b', 'c':'d'}
    if lookup_type == 'exact':
        return self.get_prep_value(value) #this returns a 'database' string
    if lookup_type == 'contains':
        return self.get_prep_value(value) 
    if lookup_type == 'icontains':
        return self.get_prep_value(value) 
    else:
        raise TypeError('Lookup type %r not supported.' % lookup_type) 

def get_internal_type(self): 
#when creating the database, it'll make the columns CharFields
    return 'CharField'

このクラスを使用するには、メイン プログラムの検索フィルターをいくつか変更する必要がありました。私は辞書を渡さなければなりませんでした。

#First find all objects that contain the following dictionary 
#Because it's icontains, I could also search with {'A':'b'}, 
#as it's case insensitive. __contains isn't case sensitive
test = MyModel.objects.filter(options__icontains = {'a':'b'})
#Note: could've used 'get' instead of filter above, 
#as I know that just one value has dict value {'a':'b'}

#Change as desired
test[0].options['a'] = 'grr'
test[0].options['ZZ'] = 'z'

#save
test[0].save() 

そして、それが2番目のテーブルを取得した方法です。

__icontains を見逃して単に書き込むと、辞書の値のみfilter(options = {'a':'b'})を持つエントリが検索され、他に何もないエントリが検索されることに注意してください。もう1つの注意点は、もちろん、より大きな辞書で検索でき、それが機能することです.{'a':'b'}

これが何人かの人々を助けることを願っています:)

于 2012-07-20T15:12:52.243 に答える
1

データベースは文字列のみを保存するため、データベース内のキーを使用して検索できる方法はありません。できることは、クエリの処理に役立つテーブルのマネージャーを構築することです。たとえば、正規表現で検索すると役立つ場合があります。 :

MyModel.objects.filter(options__regex=r'a : b')
MyModel.objects.filter(options__regex=r'.*c : d')

それらは通常のクエリであり、マネージャーを使用すると、その情報を取得して使用できます。

現在、Python クラスに辞書を保存するために使用される人気のあるライブラリがあり、それを使用することを勧めします。

于 2012-07-19T03:05:49.563 に答える