4

我有一个如下所示的 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 时才能得到结果

有任何想法吗,

谢谢

4

4 回答 4

13

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

例子

# 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)
于 2015-08-28T08:10:55.513 回答
1

返回一个查询集

permissions = Permission.objects.all()

将结果添加到多对多字段(注意*

group = MyGroup.objects.get(name='test')
group.permissions.add(*permissions)
于 2019-05-21T07:18:24.920 回答
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')

然后,您可以使用一个不错的 QuerySet:

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

次要地址

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

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

使用Q 对象完成此操作,并从中获取当前选定的对象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 地址。

于 2012-08-18T00:08:13.410 回答
0

我来到这里是因为我有一个模型,其中有一个指向这个模型“CampaignsProducts”的模型,它的str属性正在生成许多查询:

前 :

class CampaignsProducts(mdlcom.CommonStructure):
 product = models.ForeignKey(
    'products.Product',
    verbose_name=u'Producto',
    null=False, on_delete=models.CASCADE,
    related_name="%(app_label)s_%(class)s_product_set",
 )
 campaign = models.ForeignKey(
    'prices.Campaigns',
    verbose_name=u'Campaña',
    null=False, on_delete=models.CASCADE,
    related_name="%(app_label)s_%(class)s_campaign_set",
 )
 def __str__(self):
    return '{} - {}'.format(self.product.name, self.campaign.name)

为了修复它,我更改了以下“ str ”属性

def __str__(self):
   return str(self.id)

Mikko 提供的解决方案挽救了我的生命:

class CouponForm(forms.ModelForm):
NO_REQUIRED = [
    'sellers', 'platforms', 'campaigns_product',
]

class Meta:
    model = mdlpri.Coupon
    fields = '__all__'

def get_campaigns_choices(self):
    qscampaigns = (
        mdlpri.CampaignsProducts.objects.all()
        .select_related("product")
        .select_related("campaign")
        .order_by("id")
    )
    choices = []
    for item in qscampaigns:
        wdescription = '{} - {}'.format(
            item.product.name, item.campaign.name
        )
        choices.append((item.id, wdescription))

    return choices

def __init__(self, *args, **kwargs):
    super(CouponForm, self).__init__(*args, **kwargs)
    for wfield in self.NO_REQUIRED:
        self.fields[wfield].required = False

个性化选择

    w = self.fields["campaigns_product"].widget
    w.choices = self.get_campaigns_choices()

变更前查询(按产品):

SELECT "products_product"."id", "products_product"."name", "products_product"."custom", "products_product"."created_at", "products_product"."updated_at", "products_product"."active", "products_product"."position", "products_product"."url", "products_product"."for_bonus_platform", "products_product"."for_cms_platform", "products_product"."for_store_platform", "products_product"."for_call_center_platform", "products_product"."for_ibk_platform", "products_product"."for_scotiabank_platform", "products_product"."for_bbva_platform", "products_product"."for_refurbished_platform" FROM "products_product" WHERE "products_product"."id" = 1

更改后查询:

SELECT "prices_campaignsproducts"."id", "prices_campaignsproducts"."date_created_at", "prices_campaignsproducts"."created_at", "prices_campaignsproducts"."updated_at", "prices_campaignsproducts"."user_id", "prices_campaignsproducts"."last_user_modified_id", "prices_campaignsproducts"."product_id", "prices_campaignsproducts"."campaign_id", "prices_campaignsproducts"."price", "prices_campaignsproducts"."is_active", "prices_campaignsproducts"."expiration_from", "prices_campaignsproducts"."expiration_to", "products_product"."id", "products_product"."name", "products_product"."custom", "products_product"."created_at", "products_product"."updated_at", "products_product"."active", "products_product"."position", "products_product"."url", "products_product"."for_bonus_platform", "products_product"."for_cms_platform", "products_product"."for_store_platform", "products_product"."for_call_center_platform", "products_product"."for_ibk_platform", "products_product"."for_scotiabank_platform", "products_product"."for_bbva_platform", "products_product"."for_refurbished_platform", "prices_campaigns"."id", "prices_campaigns"."date_created_at", "prices_campaigns"."created_at", "prices_campaigns"."updated_at", "prices_campaigns"."user_id", "prices_campaigns"."last_user_modified_id", "prices_campaigns"."name", "prices_campaigns"."is_active" FROM "prices_campaignsproducts" INNER JOIN "products_product" ON ("prices_campaignsproducts"."product_id" = "products_product"."id") INNER JOIN "prices_campaigns" ON ("prices_campaignsproducts"."campaign_id" = "prices_campaigns"."id") ORDER BY "prices_campaignsproducts"."id" ASC

只是想分享我的经验。

最好的祝福,

于 2020-02-20T03:01:31.313 回答