将查询集结果插入ManytoManyfield

use*_*158 1 django

我有一个如下所示的models.py文件:

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"
Run Code Online (Sandbox Code Playgroud)

我有一个系统中的IP和服务器列表.我试图让ManytoManyField只显示当前未与服务器关联的IP列表.

我有以下queryset:

inner_qs = Servers.objects.values_list('ip_address_id', flat=True)
entries = Address.objects.exclude(id__in=inner_qs)
Run Code Online (Sandbox Code Playgroud)

它仅返回不在Server表中的IP地址.我不知道如何将这些结果合并到我的ManytoManyField中以及我应该放置查询集的位置.我目前只在进入django Shell时才得到结果

有任何想法吗,

谢谢

Dr *_*tan 7

如果要将查询集添加到多对多字段,请先将其更改为列表,然后使用*将其添加为位置参数

# 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)
Run Code Online (Sandbox Code Playgroud)


小智 0

您可以在此处使用此答案:Filter ManyToMany box in Django Admin

简而言之,您需要创建一个扩展的自定义表单django.forms.ModelForm。在__init__-method 中,将新选项放置到右侧小部件 ( secondary_ips)。最后,添加form = YourOwnFormServerAdmin您正在使用的类中。

我建议related_namesServers-model 中修改:

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')
Run Code Online (Sandbox Code Playgroud)

然后,你可以使用一个很好的查询集:

allowed_addresses = Address.objects.filter(server=None)
Run Code Online (Sandbox Code Playgroud)

辅助地址

当然,这只会过滤某些服务器中作为主 IP 的 IP。如果您还想过滤掉其他服务器中作为 secondary_ip 的 ip,事情会变得有点棘手:

您还需要过滤servers_secondary=None。但您不能过滤掉为当前对象(在后台编辑的服务器)选择的IP,否则这些选择的IP也会消失。

使用Q 对象来完成此操作,并从 中抓取当前选定的对象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
Run Code Online (Sandbox Code Playgroud)

主要地址下拉菜单

按照同样的方法,也可以在主IP地址下拉菜单中过滤项目。当然,必须注意不要将选定的 IP 地址从列表中删除。