0

나는이 모양의 모델을 가지고 있으며 데이터를 키 - 값 쌍으로 저장합니다.관리자로부터 사용자 정의 모델 인스턴스 반환

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) 같은 쿼리 할 때 내 over-raidden 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 

나는 자세한 정보를 얻으 려했지만 더 잘 설명해야한다고 알려주었습니다. 장고 모델이이 시나리오를 허용하는지 잘 모르겠습니다.

감사합니다.


편집 : 사용 프록시 모델

내가 정상 getsave 방법으로 키 값 필드 및 사용자 정의 프록시 모델을 저장하는 기본 모델을 가진 즉, 프록시 모델을 사용하여 수행 할 수있는이 뭔가?

답변

0

다음은 내가 한 일입니다.

정보를 키 값 쌍으로 저장 한 모델이 있었기 때문에 모델에 ModelForm을 빌드해야했지만 ModelForm은 키 - 값 쌍을 필드로 표시해야합니다 (예 : 행을 열로 피벗). 기본적으로 모델의 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 

이 관리자는이 추상 모델의 인스턴스를 인스턴스화합니다 :

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() 메소드를 오버라이드 (override)이에서 사용자 정의 관리자를 건설했다. 이 프록시는 내 모델에서 키 - 값 쌍으로 내 ModelFom의 표시 및 저장을 원하는 모든 필드가

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) 
        ) 

(장고 오류를 포기하지 않도록 추상 모델은 테이블이 없습니다). 이제 더 많은 필드를 추가해야하는 경우이 추상 모델을 수정하고 실제 모델 자체를 편집 할 필요가 없습니다. 이제 모델이 생겼으므로 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 문서를 통해 많은 파기가 필요했습니다.