2012-08-17 15 views
0

我有一個models.py文件看起來像這樣:插入查詢集成果轉化爲ManytoManyfield

from django.db import models 
from common.models import Record 
from tinymce import models as tinymce_models 

# Create your models here. 
class Address(Record): 
    def __unicode__(self): 
     return unicode(self.ip) 

    ip = models.IPAddressField(unique=True) 
    notes = models.TextField(blank=True) 

    class Meta: 
     verbose_name_plural = "Addresses" 

class Servers(models.Model): 
    def __unicode__(self): 
     return unicode(self.server_name) 

    server_name = models.CharField(max_length=100) 
    ip_address = models.ForeignKey(Address) 
    secondary_ips = models.ManyToManyField(Address, verbose_name = 'Secondary IPs', blank=True, related_name='secondary_ips') 

    class Meta: 
     verbose_name_plural = "Servers" 

我有IP的和服務器系統的列表。我試圖讓ManytoManyField只顯示當前沒有與服務器關聯的IP列表。

我有以下查詢集:

inner_qs = Servers.objects.values_list('ip_address_id', flat=True) 
entries = Address.objects.exclude(id__in=inner_qs) 

它只返回那些未在Server表中的IP地址。我不知道如何將這些結果合併到我的ManytoManyField中,以及我應該放置查詢集的位置。我目前只得到了結果,當我進入Django的殼牌

任何想法,

感謝

+0

什麼是你想用做ips沒有連接到服務器? – dm03514 2012-08-17 17:01:50

+0

我想讓這些IP在我的admin.py文件中的filter_horizo​​ntal =('secondary_ips')中顯示。那些應該是我可以選擇的唯一IP。相反,它列出了我的地址表中的所有IP地址。 – user1607158 2012-08-17 19:23:54

回答

0

你可以使用這個答案在這裏:Filter ManyToMany box in Django Admin

總之,你需要創建一個自定義窗體延伸django.forms.ModelForm。在那裏,在__init__-方法中,將新選項放置到正確的小部件(secondary_ips)。最後,將form = YourOwnForm添加到您正在使用的ServerAdmin類中。

我建議在Servers -model修改related_names

class Servers(models.Model): 
    # ... 
    ip_address = models.ForeignKey(Address, related_name='server') 
    secondary_ips = models.ManyToManyField(Address, verbose_name = 'Secondary IPs', \ 
     blank=True, related_name='servers_secondary') 

然後,你可以用一個漂亮的QuerySet:

allowed_addresses = Address.objects.filter(server=None) 

次地址

當然,這種過濾器只有在某些服務器中作爲主要IP的IP。如果你想過濾出在其他服務器上作爲secondary_ip的ips,那麼事情會變得有點棘手:

您還需要篩選servers_secondary=None。但是不能過濾出爲當前對象選擇的IP(在管理員中編輯的服務器),或者那些選定的IP也將消失。

使用Q objects完成此操作,並從kwargs中獲取當前選定的對象。那麼您的自定義窗體的__init__ - 方法會是這個樣子:

def __init__(self, *args, **kwargs): 
    super(YourOwnForm, self).__init__(*args, **kwargs) 
    instance = kwargs.get('instance') 
    allowed_addresses = Address.objects \ 
     .filter(server=None) \ 
     .filter(Q(servers_secondary=None) | Q(servers_secondary=instance)) 
    choices = [] 
    for choice in allowed_addresses: 
     choices.append((choice.id, choice.ip)) 
    w = self.fields['secondary_ips'].widget 
    w.choices = choices 

主地址下拉菜單

如下因素同樣的方法,也可以過濾在主IP地址下拉列表項菜單。當然,必須注意不要從列表中刪除選定的IP地址。

+0

謝謝Mikko。我會嘗試一下,讓知道發生了什麼。 – user1607158 2012-08-20 13:40:48

+0

嗨Mikko,它工作,如果我已經有數據庫中列出的服務器通過加載它們通過固定裝置。但是,如果我從一個乾淨的數據庫開始,我可以添加IP的就好了,但是當我嘗試添加一臺服務器,我得到了以下錯誤:異常類型:\t KeyError異常 異常值:再次\t 「實例」 – user1607158 2012-08-20 14:45:32

+0

您好,我能夠通過添加一個try/except來修復它。請嘗試: instance = kwargs ['instance'] 除外: instance = None再次感謝您的幫助。 – user1607158 2012-08-20 14:50:43

4

如果你想一個查詢集的許多添加到許多領域的第一,改變成一個列表,並使用其添加爲定位參數*

# Returns a queryset 
permissions = Permission.objects.all() 

# Add the results to the many to many field (notice the *) 

group = MyGroup.objects.get(name='test') 

group.permissions.add(*permissions) 
+0

兩個查詢,而不是一個:( – DylanYoung 2017-02-27 20:04:44

+0

@DylanYoung如果你有辦法做到一個查詢請分享 – 2017-02-28 13:55:35

+0

其實我錯了;這是三個查詢。這樣的事情在兩個,假設你知道組PK:對於Permission.objects.all()中的permission_id,通過模型= MyGroup.permissions.through;通過模型.objects.bulk_create(通過模型(權限= permission_id,mygroup = group_pk)) – DylanYoung 2017-03-08 12:04:07