2016-05-23 78 views
0

我想創建一個簡單的動作,從數據庫中獲取一條記錄(與ManyToMany關係),然後顯示JSON序列化的實例,這裏是我現在是如何做到的:Django模型實例字段與Dict ManyToMany關係

服務模式:

class SystemService(models.Model): 
    name = models.CharField(max_length=35, unique=True, null=False, blank=False) 
    verion = models.CharField(max_length=35, unique=True, null=False, blank=False) 

    def __str__(self): 
     return self.name 

服務器型號:

class Server(models.Model): 
    name = models.CharField(max_length=35, unique=True, null=False, blank=False) 
    ip_address = models.GenericIPAddressField(protocol='both', unpack_ipv4=True, 
               null=False, blank=False, unique=True) 
    operating_system = models.ForeignKey(OperatingSystem, null=False, blank=False) 
    monitored_services = models.ManyToManyField(SystemService) 
    info = models.CharField(max_length=250, null=True, blank=True) 
    pause_monitoring = models.BooleanField(default=False) 
    created_at = models.DateTimeField(auto_now_add=True) 
    updated_at = models.DateTimeField(auto_now=True) 

    def __str__(self): 
     return self.name 

這是怎麼回事現在使用MUJ加布裏埃爾回答:

def get_server(request, server_id): 
    try: 
     server_object = Server.objects.get(id=server_id) 
     data = { 
      'name': server_object.name, 
      'ip_address': server_object.ip_address, 
      'os': server_object.operating_system.name, 
      'info': server_object.info, 
      'monitoring_paused': server_object.pause_monitoring, 
      'created_at': server_object.created_at, 
      'update_at': server_object.updated_at, 
      'services': {service['id']: service['name'] for service 
        in server_object.monitored_services.values('id', 'name')} 
     } 
     return JsonResponse(data) 
    except Server.DoesNotExist: 
     return JsonResponse({'error': 'Selected object does not exits!'}) 

我不認爲我做的不夠好,因爲我每一次我需要得到一個實例作爲JSON重複同樣的事情,所以我想知道是否有一個Python的和動態的方式來做到這一點?

回答

0

在Django的文檔看起來有點後,我發現了model_to_dict功能,基本上做什麼,我需要(模型實例字典),但對於ManyToMany關係,它只返回一個PK列表,所以我寫了我自己的基礎上的功能:

def db_instance2dict(instance): 
    from django.db.models.fields.related import ManyToManyField 
    metas = instance._meta 
    data = {} 
    for f in chain(metas.concrete_fields, metas.many_to_many): 
     if isinstance(f, ManyToManyField): 
      data[str(f.name)] = {tmp_object.pk: db_instance2dict(tmp_object) 
           for tmp_object in f.value_from_object(instance)} 
     else: 
      data[str(f.name)] = str(getattr(instance, f.name, False)) 
    return data 

希望它可以幫助別人。

1

如果你只需要值「身份證」和「名」,我建議使用此:

'services': {service['id']: service['name'] 
      for service in server_object.monitored_services.values('id', 'name')} 

django docs

您也可以將代碼移植到一個屬性Model類重用它在別處。

class Server(models.Model): 
    ....... 

    @property 
    def data(self): 
     return { 
      'name': self.name, 
      'ip_address': self.ip_address, 
      'os': self.operating_system.name, 
      'info': self.info, 
      'monitoring_paused': self.pause_monitoring, 
      'created_at': self.created_at, 
      'update_at': self.updated_at, 
      'services': {service['id']: service['name'] for service in self.monitored_services.values('id', 'name')} 
     } 

你的瀏覽功能將是:

def get_server(request, server_id): 
    try: 
     server_object = Server.objects.get(id=server_id) 
     return JsonResponse(server_object.data) 
    except Server.DoesNotExist: 
     return JsonResponse({'error': 'Selected object does not exits!'}) 
+0

Thanx爲您的答案我用它來改善我的代碼,當我說我不想每次重複同樣的事情,我的意思是其他模型,所以我正在尋找一種獨特的方式來做它適用於任何模型的實例。 – ddalu5

+1

正如我在answear中所說的,在Model類中創建一個@property並將代碼移到那裏 –

+0

我是指另一個模型(而不僅僅是Server)實例,對不起,我沒有很好地解釋我自己。 – ddalu5