为什么model.m2mRelation.remove()不起作用?

时间:2011-02-15 13:35:59

标签: django

换句话说,为什么这样做:

if choice==Item.DO_ADD_CAT:
    for item in selected_items:
        for c in categories:
            item.categories.add(Category.objects.get(pk=c))
        item.save()
    messages.success(request,'Categories have been added.')

而这不是:

if choice==Item.DO_REM_CAT:                        
    for item in selected_items:                            
        for c in categories:                                 
            item.categories.remove(Category.objects.get(pk=c))
        item.save()                            
    messages.success(request,'Categories have been removed.')

这不应该起作用吗?

修改 这是Item模型:

class Item(models.Model):
    #public/private state flags
    PRIVATE_STATUS=1
    PUBLIC_STATUS=2
    RELEASED_STATUS=3
    STATUS_CHOICES=((PRIVATE_STATUS ,'private'),
                    (PUBLIC_STATUS  ,'public' ),
                    (RELEASED_STATUS,'released'))
    status = models.IntegerField(choices=STATUS_CHOICES,
                                 default=PRIVATE_STATUS,
                                )
    objects = models.Manager()
    name=models.CharField(max_length=50)
    tags=TagField()
    count=models.IntegerField(blank=True)

    def get_user_path(self,filename):
        return '%s/%s/%s' %( self.creator_id,
                             datetime.date.today(),
                             filename)
    file=models.FileField(upload_to=get_user_path)

    creator = models.ForeignKey(User, related_name='creator')
    categories = models.ManyToManyField(Category,related_name="items",blank=True,null=True)  

和类别模型:

class Category (models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField()
    description = models.TextField(blank=True,help_text='Optional')

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name='Category'
        verbose_name_plural='Categories'

2 个答案:

答案 0 :(得分:0)

这正是它应该如何工作(特别是如果第一种方法有效)。

您收到错误消息吗?你怎么知道它不起作用?

您的代码是否已进入删除阶段?使用import pdb; pdb.set_trace()和/或胡椒与print / log语句,以确保完全符合if条件,以及是否存在您要删除的对象。

我会在你的循环中输入pdb并检查哪些类别存在并尝试删除其中一个。

if choice==Item.DO_REM_CAT:                        
    for item in selected_items:                            
        for c in categories:
            import pdb; pdb.set_trace()
            # now check loop.categories.all()
            # item.categories.get(pk=c)
            item.categories.remove(Category.objects.get(pk=c))                              
    messages.success(request,'Categories have been removed.')



log = []
if choice==Item.DO_REM_CAT:                        
    for item in selected_items:                            
        for c in categories:
            category = Category.objects.get(pk=c)
            try:
                item.categories.get(pk=category.pk) # just making sure what we're deleting really exists
                item.categories.remove(category.pk)
                try:
                    item.categories.get(pk=category.pk) # shouldn't be here anymore
                    log.append("Category %s Magically Still Here" %  category)
                except Category.DoesNotExist:
                    log.append("Category %s Successfully Deleted" % category)
            except Category.DoesNotExist:
                log.append("Category %s we attempted to remove from %s doesn't exist" % (category, item))

            return http.HttpResponse('<br><br>'.join(log))

答案 1 :(得分:0)

我想我看到了错误......正如在django文档中告诉我们的那样,你不能在具有null = False定义的外键上使用remove ... Related documentation

所以在M2M关系的逻辑之前,django将你的m2m关系设置为null = False ......所以可能性是:

  1. 将您的m2m定义更改为null = True
  2. 使用clear()删除所有元素......