У меня довольно простая пользовательская модель, отлично работающая. Чтобы уменьшить избыточность кода, я стараюсь хранить поля внутри диктовки по причинам, которые легко догадаться.

Примере:

def get_social_token(self,social_net=""):
   return self.social_dict[social_net]["token"]

Если я не делаю такую структуру, я должен сделать "если / то ... элиф ... еще". И, конечно, мне нужно изменить свой код всякий раз, когда я решаю добавить новую социальную сеть в свое приложение.

Я попробовал два разных подхода, оба они дают мне один и тот же результат:

  • Нет ошибки
  • В БД поле фактически не обнаружено и не создано

Я хотел бы упомянуть, что если я использую «обычный способ» для реализации такого поведения, как:

  • twitter_social_token = EncryptedCharField (max_length = 500, default = '', blank = True, null = True)

Это прекрасно работает, так что это происходит от использования словаря.

Есть идеи, чтобы решить это? Btw . Я бы предпочел избегать использования новой модели и внешнего ключа ... Только связь один-к-одному, я бы предпочел не выполнять какое-либо "соединение" или выбирать в другой таблице ...

Ниже вы найдете две попытки, которые я сделал, но они не работают (и я не знаю почему):

Первая попытка .

social_fields = {
    'twitter' : {
        'token'  : EncryptedCharField(max_length=500, default='', blank=True, null=True),
        'secret' : EncryptedCharField(max_length=500, default='', blank=True, null=True)
    },
    'facebook' : {
        'token'  : EncryptedCharField(max_length=500, default='', blank=True, null=True),
        'secret' : EncryptedCharField(max_length=500, default='', blank=True, null=True)
    },
    'gplus' : {
        'token'  : EncryptedCharField(max_length=500, default='', blank=True, null=True),
        'secret' : EncryptedCharField(max_length=500, default='', blank=True, null=True)
    },
    'linkedin' : {
        'token'  : EncryptedCharField(max_length=500, default='', blank=True, null=True),
        'secret' : EncryptedCharField(max_length=500, default='', blank=True, null=True)
    },
}

Вторая попытка .

social_tokens = dict()

social_tokens["twitter"] = dict()
social_tokens["facebook"] = dict()
social_tokens["linkedin"] = dict()
social_tokens["gplus"] = dict()

social_tokens["twitter"]["token"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)
social_tokens["twitter"]["secret"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)

social_tokens["facebook"]["token"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)
social_tokens["facebook"]["secret"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)

social_tokens["linkedin"]["token"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)
social_tokens["linkedin"]["secret"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)

social_tokens["gplus"]["token"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)
social_tokens["gplus"]["secret"] = EncryptedCharField(max_length=500, default='', blank=True, null=True)

Спасибо за помощь дорогие друзья,

Джонатан

0
Jonathan DEKHTIAR 1 Апр 2017 в 14:48

2 ответа

Лучший ответ

Это определенно сработает, однако, как вы видели, я использую зашифрованные поля для защиты токенов моего пользователя и секретных токенов.

Я надеюсь, что это не плохая вещь или какой-то анти-паттерн. Не стесняйтесь поделиться лучшим способом сделать это.

Я только что нашел обходной путь, который на самом деле работает именно так, как я хотел, даже если он не очень эффективен с моей точки зрения.

Вот вам доступ к данным:

from application.models import *
tmp_user = CustomUser.objects.get(username="random_username")

print (getattr(tmp_user, tmp_user.social_fields["twitter"]["token"]))
>>> e72e16c7e42f292c6912e7710c838347ae178b4a ### This token is a fake !

Вот как это удалось сделать:

twitter_token          = EncryptedCharField(max_length=500, default='', blank=True, null=True)
twitter_token_secret   = EncryptedCharField(max_length=500, default='', blank=True, null=True)

facebook_token         = EncryptedCharField(max_length=500, default='', blank=True, null=True)
facebook_token_secret  = EncryptedCharField(max_length=500, default='', blank=True, null=True)

gplus_token            = EncryptedCharField(max_length=500, default='', blank=True, null=True)
gplus_token_secret     = EncryptedCharField(max_length=500, default='', blank=True, null=True)

linkedin_token         = EncryptedCharField(max_length=500, default='', blank=True, null=True)
linkedin_token_secret  = EncryptedCharField(max_length=500, default='', blank=True, null=True)

social_fields = {
    'twitter' : {
        'token'  : "twitter_token",
        'secret' : "twitter_token_secret"
    },
    'facebook' : {
        'token'  : "facebook_token",
        'secret' : "facebook_token_secret"
    },
    'gplus' : {
        'token'  : "gplus_token",
        'secret' : "gplus_token_secret"
    },
    'linkedin' : {
        'token'  : "linkedin_token",
        'secret' : "linkedin_token_secret"
    },
}
1
Jonathan DEKHTIAR 1 Апр 2017 в 12:30

Насколько я знаю, без использования join у вас есть 3 разных способа:

django-picklefield обеспечивает реализацию поля маринованного объекта. Такие поля могут содержать любые выбираемые объекты.

Из их документации, чтобы использовать; просто определите поле в вашей модели:

>>> from picklefield.fields import PickledObjectField
... class SomeObject(models.Model):
...     args = PickledObjectField()

И назначьте на поле все, что вам нравится (если это возможно):

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()

django-jsonfield - это повторно используемое поле Django, которое позволяет вам хранить проверенный JSON в вашей модели. Он молча заботится о сериализации. Чтобы использовать, просто добавьте поле к одной из ваших моделей.

Чтобы использовать, просто установите пакет, а затем используйте поле:

from django.db import models
import jsonfield

class MyModel(models.Model):
    the_json = jsonfield.JSONField()
  • hstorefield, если вы используете PostgreSQL

Поле для хранения отображений строк в строки. Используемый тип данных Python является диктатом.

from django.contrib.postgres.fields import HStoreField
from django.db import models

class Dog(models.Model):
    name = models.CharField(max_length=200)
    data = HStoreField()

Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
2
mdegis 1 Апр 2017 в 12:06