Возврат пользовательского экземпляра модели от менеджера - PullRequest
0 голосов
/ 09 сентября 2011

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

class Setting(models.Model):
    company = models.ForeignKey(
        Company
    )
    name = models.CharField(
        null=False, max_length=255
    )
    value= models.CharField(
        null=False, max_length=255
    )

У меня есть пользовательский менеджер для этой модели, который переопределяет метод get.Когда запросы моей модели похожи на Settings.objects.get(company=1), я использую мой переопределенный метод get, чтобы выполнить self.objects.filter(company=1), который возвращает список объектов.Могу ли я создать один пользовательский QuerySet, который имеет все пары ключ-значение в качестве полей.

Пример:

Если бы данные в моей модели были такими:

company  name    value
-------  ----    -----
1        theme   custom
1        mode    fast
1        color   green

Я хотел бы вернуть набор запросов, который был бы повернут таким образом, когда кто-товыполнено Settings.objects.get(company=1):

company  theme    mode     color
------   -----    ----     -----
1        custom   fast     green

Я пытался быть многословным, но дайте мне знать, если мне лучше объяснить.Я не уверен, что модели Django допускают такой сценарий.

Спасибо всем.


Редактировать: Использование прокси-моделей

Это то, что я мог бы сделать, используяПрокси-модели, т.е. имеющие базовую модель для хранения полей значений ключа и пользовательскую прокси-модель с обычным методом get и save?

1 Ответ

0 голосов
/ 14 сентября 2011

Вот как я это сделал.

Мне нужно было сделать это, потому что у меня была Модель, которая хранила информацию в виде пар ключ-значение, и мне нужно было построить ModelForm для этой Модели, но ModelForm должен отображать пары ключ-значение в виде полей, то есть поворачивать строки в столбцы. По умолчанию метод get() в модели всегда возвращает сам экземпляр модели, и мне нужно было использовать собственную модель. Вот как выглядела моя модель пары ключ-значение:

class Setting(models.Model):
    domain = models.ForeignKey(Domain)
    name = models.CharField(null=False, max_length=255)
    value = models.CharField(null=False, max_length=255)

    objects = SettingManager()

Я создал собственный менеджер для переопределения метода get():

class SettingManager(models.Manager):

    def get(self, *args, **kwargs):
        from modules.customer.proxies import *
        from modules.customer.models import *

        object = type('DomainSettings', (SettingProxy,), {'__module__' : 'modules.customer'})()
        for pair in self.filter(*args, **kwargs): setattr(object, pair.name, pair.value)

        setattr(object, 'domain', Domain.objects.get(id=int(kwargs['domain__exact'])))
        return object

Этот менеджер будет создавать экземпляр этой абстрактной модели. (Абстрактные модели не имеют таблиц, поэтому Django не выдает ошибок)

class SettingProxy(models.Model):

    domain = models.ForeignKey(Domain, null=False, verbose_name="Domain")
    theme = models.CharField(null=False, default='mytheme', max_length=16)
    message = models.CharField(null=False, default='Waddup', max_length=64)

    class Meta:
        abstract = True

    def __init__(self, *args, **kwargs):
        super(SettingProxy, self).__init__(*args, **kwargs)
        for field in self._meta.fields:
            if isinstance(field, models.AutoField):
                del field

    def save(self, *args, **kwargs):
        with transaction.commit_on_success():
            Setting.objects.filter(domain=self.domain).delete()

            for field in self._meta.fields:
                if isinstance(field, models.ForeignKey) or isinstance(field, models.AutoField):
                    continue
                else:
                    print field.name + ': ' + field.value_to_string(self)
                    Setting.objects.create(domain=self.domain,
                        name=field.name, value=field.value_to_string(self)
                    )

Этот прокси-сервер имеет все поля, которые я хотел бы отобразить в моем ModelFom и сохранить как пары ключ-значение в моей модели. Теперь, если мне когда-нибудь понадобится добавить больше полей, я могу просто изменить эту абстрактную модель и не нужно редактировать саму модель. Теперь, когда у меня есть модель, я могу просто построить на ней ModelForm следующим образом:

class SettingsForm(forms.ModelForm):

    class Meta:
        model = SettingProxy
        exclude = ('domain',)

    def save(self, domain, *args, **kwargs):
        print self.cleaned_data
        commit = kwargs.get('commit', True)
        kwargs['commit'] = False
        setting = super(SettingsForm, self).save(*args, **kwargs)
        setting.domain = domain
        if commit:
            setting.save()
        return setting

Надеюсь, это поможет. Чтобы понять это, потребовалось много копаться в документации по API.

...