Django - F('datetimefield')+ relativedelta(月= 1)失败

时间:2016-12-25 15:51:28

标签: python django python-dateutil relativedelta

我正在尝试使用django中的F()对象更新模型的自我日期时间字段。

HeatWatchList.objects.filter(
    user=request.user,
    next_date_to__lt=datetime.combine(datetime.now().date(), time.min)
).update(
    next_date_from = F('next_date_from') + relativedelta(months=1),
    next_date_to = F('next_date_to') + relativedelta(months=1)
)

但是这样做的时候我得到AttributeError: relativedelta object has no attribute translate

这是我在执行代码时得到的回溯可能在使用日期时间类型relativedelta添加值时使用F()对象时出现问题。

Traceback (most recent call last):
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\views\decorators\csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\rest_framework\viewsets.py", line 83, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\rest_framework\views.py", line 477, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\rest_framework\views.py", line 437, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\rest_framework\views.py", line 474, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\farm_management\heat\views.py", line 192, in update_watchlist
    next_date_to = F('next_date_to') + relativedelta(months=1)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\models\query.py", line 637, in update
    rows = query.get_compiler(self.db).execute_sql(CURSOR)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\models\sql\compiler.py", line 1148, in execute_sql
    cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\models\sql\compiler.py", line 835, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\django\db\backends\mysql\base.py", line 110, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\cursors.py", line 164, in execute
    query = self.mogrify(query, args)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\cursors.py", line 143, in mogrify
    query = query % self._escape_args(args, conn)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\cursors.py", line 118, in _escape_args
    return tuple(conn.literal(arg) for arg in args)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\cursors.py", line 118, in <genexpr>
    return tuple(conn.literal(arg) for arg in args)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\connections.py", line 800, in literal
    return self.escape(obj, self.encoders)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\connections.py", line 793, in escape
    return escape_item(obj, self.charset, mapping=mapping)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\converters.py", line 27, in escape_item
    val = encoder(val, mapping)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\converters.py", line 110, in escape_unicode
    return u"'%s'" % _escape_unicode(value)
  File "C:\Users\Web\Desktop\PyDev\Envs\djangular\lib\site-packages\pymysql\converters.py", line 73, in _escape_unicode
    return value.translate(_escape_table)
AttributeError: 'relativedelta' object has no attribute 'translate'

2 个答案:

答案 0 :(得分:1)

好像是pymysql的转换器does not support relativedelta对象。 一种可能的解决方案是迭代对象并更新它(效率低下):

objects_list = HeatWatchList.objects.filter(
user=request.user,
next_date_to__lt=datetime.combine(datetime.now().date(), time.min)
)

for obj in object_list:
    obj.next_date_from = onj.next_date_from + relativedelta(months=1)
    obj.next_date_to = onj.next_date_to + relativedelta(months=1)
    objsave()  

如果有可能,最好使用datetime.timedelta代替relativedelta

HeatWatchList.objects.filter(
user=request.user,
next_date_to__lt=datetime.combine(datetime.now().date(), time.min)
).update(
next_date_from = F('next_date_from') + timedelta(days=31),
next_date_to = F('next_date_to') + timedelta(days=31)
)

答案 1 :(得分:0)

从PostgreSQL documentation中,发现1个月的间隔被视为30天:

enter image description here

因此,与使用timedelta(days=30)的情况和使用relativedelta(months=1)的情况(如果使用的是PostgreSQL)相同。您只需添加F()timedelta为30天(即F('datetimefield') + timedelta(days=30))的表达式即可