django - 将查询集结果插入到多对多字段中

标签 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"

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

我有以下查询集:
inner_qs = Servers.objects.values_list('ip_address_id', flat=True)
entries = Address.objects.exclude(id__in=inner_qs)

它只返回不在服务器表中的 IP 地址。我不知道如何将这些结果合并到我的 ManytoManyField 以及我应该在哪里放置查询集。我目前只有在进入 django Shell 时才能得到结果

有任何想法吗,

谢谢

最佳答案

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

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

我建议在 related_names -model 中修改 Servers:

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 的 ip,事情会变得有点棘手:

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

使用 Q objects 完成此操作,并从 kwargs 中获取当前选定的对象。您的自定义表单的 __init__ -method 将如下所示:
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 地址。

关于django - 将查询集结果插入到多对多字段中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12009658/

相关文章:

javascript - Javascript的CryptoJS.enc.base64.stringify(data)在Python3/Django中的逆运算是什么?

python - 获取模板中所有自定义用户的列表(Django)

Django缓存一个大列表

python - python中的正则表达式和unicode utf-8?

python - Django 二进制或 BLOB 模型字段

django - TemplateView的get方法: object has no attribute 'request'

django - 模块未找到错误: No module named 'gunicorn'

python - 具有多个匹配项的 Django 查询

python - 我在 django 中不断收到以下错误 : "UnboundLocalError at/myapp/"

django完成电子邮件验证