【问题标题】:Remove element from ArrayField of PostgreSQL in Django从 Django 中 PostgreSQL 的 ArrayField 中删除元素
【发布时间】:2015-05-15 14:50:35
【问题描述】:

我正在使用 django 1.8a1 并且我的模型是这样的 --

from django.contrib.postgres.fields import ArrayField
from django.contrib.auth.models import User
# Create your models here.

class cart(models.Model):
    user = models.ForeignKey(User, blank=True, null=True)
    cart_details = ArrayField(models.CharField(max_length=200), null=True, blank=True)
    def __str__(self):  # __unicode__ on Python 2
        return self.name.username

我的postgres db 中有这样一行

select * from cart_cart;
 id |          cart_details           | user_id 
----+---------------------------------+---------
  1 | {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2} |       1

我想删除购物车详情中的一些商品

我写了以下代码

obj = cart.objects.filter(user=request.user, cart_details__contains=[product_id])
if obj.exists():
    obj[0].cart_details = obj[0].cart_details.remove(str(product_id))
    obj[0].save()

我也尝试过类似的方法,但这也没有用

print obj[0].cart_details
[u'2', u'2', u'2', u'2', u'2', u'2', '2']
lis1=obj[0].cart_details
lis1.remove('2')
print lis1
[u'2', u'2', u'2', u'2', u'2', u'2',]
obj[0].cart_details = lis1
obj.save()
print obj[0].cart_details
[u'2', u'2', u'2', u'2', u'2', u'2', '2']

不知道我做错了什么。任何帮助将不胜感激

【问题讨论】:

    标签: python django postgresql django-1.8


    【解决方案1】:

    您需要从数据库中刷新obj[0],因为对数据库的更改不会自动反映到已加载的对象实例。

    obj.save()
    obj_refreshed = cart.objects.filter(user=request.user, cart_details__contains=[product_id]) 
    print(obj_refreshed[0].card_details)
    

    我还建议您关注PEP-8 Python style guide 并将您的班级名称大写。

    【讨论】:

    • 无法获得想要的结果。即使保存后,更改也不会反映在数据库中.....
    • 如何检查更改是否在数据库中?你还记得提交你的数据库事务吗?
    • 问题出在 cart_details 列上...在除 ArrayField 之外的任何其他类型的列上,我都能够使用 obj.save() 方法更新值...无需在数据库上进行手动提交。我认为它们是 ArrayField 类型的列的一些问题。 django orm 无法处理这种字段(可能是因为 django 1.8 还在开发阶段)
    • 请回复:如何检查更改是否在数据库中?发布您的代码。
    • 我刚刚做了一个'select * from '来确认该行是否已经更新。
    【解决方案2】:

    我可以通过稍微修改代码来更新 cart_details 列(虽然我无法理解原因)

    product_id = str(request.data.get('product_id'))
    obj = cart.objects.filter(user=request.user, cart_details__contains=[product_id])
    if obj.exists():
        # This didnt work....
        #obj[0].cart_details.remove(product_id)
        #obj[0].save()
        #print obj[0].cart_details
    
        # This works....
        cart_object = obj[0]
        cart_object.cart_details.remove(product_id)
        cart_object.save()
        #print cart_object.cart_details
    

    【讨论】:

    • 我认为您看到的是 Django ORM 中的惰性求值。具体来说,只有当您说 obj[0] 并获取您的行时,查询才会真正运行。在注释掉的示例中,您获取一次并从数组字段中删除某些内容。然后,您再次调用obj[0],它从数据库运行另一个干净的提取,并保存第二个未更改的提取对象。如此有效,您什么都不做。
    【解决方案3】:

    如果要删除的元素不在该列表中,则直接访问card_details 会引发ValueError

    但你可以这样做:

    from django_postgres_extensions.models.functions import ArrayRemove
    cart.objects.filter(
       cart_details__contains=[element]
    ).update(
       cart_details=ArrayRemove('cart_details', element)
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      • 2020-10-21
      • 2013-02-14
      • 1970-01-01
      • 2017-04-29
      相关资源
      最近更新 更多