【问题标题】:Django Newbie ManyRelated Manager not Iterable QuestionDjango Newbie ManyRelated Manager not Iterable Question
【发布时间】:2024-01-24 11:31:01
【问题描述】:

我正在尝试通过组合来自其他两个字段的元素(其中一个是 ManyToManyField)来创建产品代码(在管理员中)。我想遍历该字段以查明是否选择了特定产品选项,并将其变体附加到该不可编辑的产品代码中,如下所示:

class ShirtColorClass(models.Model):
    shirtcolor = models.CharField(_('Shirt Color'), unique=True, max_length=40)
    def __unicode__(self):
        return self.shirtcolor

class ShirtClass(models.Model):
    shirtmodel = models.CharField(_('Model of Shirt'), max_length=40)
    shirtclr = models.ManyToManyField(_(ShirtColorClass, verbose_name='Shirt Color'))
    shirtcode = models.CharField(_('Code for the shirt'), max_length=80, editable=False)
    #...10 more fields...
    def __unicode__(self):
        return self.shirtmodel
    def save(self):
        for item in self.shirtclr: #these are the lines I'm not sure how to do
            if 'Blue' in self.shirtclr:
                self.shirtcode = u'%s%s' % ('B', self.shirtmodel)
            else:
                self.shirtcode = self.shirtmodel
            super(ShirtClass,self).save()

目前我收到一个 ManyRelatedManager not Iterable 消息,所以我知道我做错了什么,但我不知道是什么......我提前为这是一个愚蠢的新手问题道歉。谢谢。

【问题讨论】:

    标签: django django-models django-admin


    【解决方案1】:

    尝试拨打.all()就可以了。

    【讨论】:

    • ...所以是这样的: def save(self): for item in self.shirtclr.all(): if item == 'Blue': self.shirtcode = u'%s% s' % ('B', self.shirtmodel) else: self.shirtcode = self.shirtmodel super(ShirtClass,self).save() 我不能让它工作...... ShirtClass not iterable 是错误。我究竟做错了什么?再次感谢您。
    • 我认为我们需要退后一步,找出您在这里实际想要完成的工作。
    • 非常感谢您的帮助。我试图通过连接前两个的组件来保存第三个字段......唯一的复杂之处是前两个中的一个是 ManyToManyField 并且我不知道在这种情况下访问其内容的正确方法。看看我在顶部输入的内容,我认为我不需要一个 for 循环......当我以前使用 Python 时,“in”在查看列表时为我完成了工作。但是,“如果 self.shirtcode.all() 中的'Blue'”似乎对我不起作用。我一直认为这不应该是一件很难完成的事情......但我错过了一些东西......
    • 也许你应该把它变成一个属性,而不是让它成为一个真正的字段。 djangoproject.com/documentation/models/propertiesb-list.org/weblog/2006/aug/18/…
    【解决方案2】:

    致电filter():

    def save(self):
        if self.pk!=None:
            if self.shirtclr.filter(shirtcolor='Blue'):
                self.shirtcode = u'%s%s' % ('B', self.shirtmodel)
            else:
                self.shirtcode = self.shirtmodel
        else:
            self.shirtcode = ''
    

    你可以通过添加default='' 来避免self.shirtcode = ''

    shirtcode = models.CharField(_('Code for the shirt'), max_length=80, editable=False, default='')
    

    【讨论】:

    • 是的(感谢您的回答……抱歉,我无法立即回复您)。如果没有现有实例,我会收到“'衬衫类'实例需要有一个主键值才能使用多对多关系”错误。如果有,则 Post 将完成,但无论我选择什么颜色, shirtcode 都将等于 shirtmodel。有什么想法吗?
    • 至于例外 - 更正了答案,现在应该可以工作了。至于 shirtcode 总是等于 shirtmodel,你确定它是 'Blue',而不是例如 'blue''blue '
    【解决方案3】:

    感谢您的回答。我将您的两个答案合并为一个...具有如下过滤器的属性:

     def _get_blue_shirts(self):
      if self.shirtclr.filter(shirtcolor='Blue'):
       return '%s%s' % ('B', self.shirtmodel)
      else:
       return self.shirtmodel
     blue_shirts=property(_get_blue_shirts)
    

    虽然这种方法确实有效,但我可以在编写它时看到它的问题。首先,我想在管理员中搜索,例如,“B13A”作为衬衫型号,并让它明白我的意思是“13A”衬衫,其中蓝色作为其颜色之一。由于 ModelAdmin.search_fields 似乎需要解析为实际字段,因此这种方法在这方面不起作用(如果我错了,请纠正我)。我担心的另一个问题是该属性似乎非常重 SQL...为每一行执行单独的选择(而专用列只需要整体选择...再次,如果我错了,请纠正我)。关于如何解决这些问题的任何想法?也许我可以采取另一种方式?

    PS。安东尼...我尝试了修改后的覆盖保存(),但仍然得到“'衬衫类'实例需要有一个主键值才能使用多对多关系”错误。我在这里做错了吗?

    非常,非常,非常感谢大家, -bkev

    【讨论】: