【问题标题】:Returning a custom model instance from a manager从管理器返回自定义模型实例
【发布时间】:2011-11-13 19:23:34
【问题描述】:

我有一个看起来像这样的模型,并将数据存储为键值对。

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 模型是否允许这种情况。

谢谢大家。


编辑:使用代理模型

这是我可以使用代理模型完成的吗,即拥有一个基本模型来存储键值字段和使用普通 getsave 方法的自定义代理模型?

【问题讨论】:

    标签: python django django-models django-queryset django-managers


    【解决方案1】:

    我是这样做的。

    我需要这样做,因为我有一个将信息存储为键值对的模型,我需要在该模型上构建一个 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 文档才能弄清楚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 2014-08-31
      • 2011-04-20
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多