我有一个看起来像这样的模型,并将数据存储为键值对。
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
方法的自定义代理模型吗?
答案 0 :(得分:0)
我是这样做的。
我需要这样做,因为我有一个模型将信息存储为键值对,我需要在该模型上构建一个ModelForm,但ModelForm应该将键值对显示为字段,即将行旋转到列。默认情况下,Model的get()
方法总是返回自身的Model实例,我需要使用自定义Model。这是我的键值对模型的样子:
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
此Manager将实例化此抽象模型的实例。 (抽象模型没有表格,因此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文档来解决这个问题。