Django: выполнение запроса UPDATE всегда возвращает rowcount 0
Я новичок в программировании и не уверен, во мне ли проблема или в коде Django. Я вызываю метод link из представления и обновляю поле MatchId
на модели Record
. База данных - SQL Server 2017.
Мое мнение:
class RecordViewSet(viewsets.ModelViewSet):
"""
API for everything that has to do with Records.
Additionally we provide an extra `link` action.
"""
queryset = Record.objects.all().order_by("Id")
serializer_class = RecordSerializer
permission_classes = [permissions.IsAuthenticated]
@action(methods=["post"], detail=False)
def link(self, request, *args, **kwargs):
idToMatch = request.POST.getlist("Id")
recordsToMatch = Record.objects.filter(Id__in=idToMatch)
lastMatchId = Record.objects.latest("MatchId").MatchId
matchedSuccesfully = recordsToMatch.update(MatchId=lastMatchId + 1)
if matchedSuccesfully > 1:
return Response(data=matchedSuccesfully, status=status.HTTP_200_OK)
else:
return Response(data=matchedSuccesfully, status=status.HTTP_404_NOT_FOUND)
По какой-то причине matchedSuccessfully всегда возвращает ноль. Соответствующий код Django:
def execute_sql(self, result_type):
"""
Execute the specified update. Return the number of rows affected by
the primary update query. The "primary update query" is the first
non-empty query that is executed. Row counts for any subsequent,
related queries are not available.
"""
cursor = super().execute_sql(result_type)
try:
rows = cursor.rowcount if cursor else 0
is_empty = cursor is None
finally:
if cursor:
cursor.close()
for query in self.query.get_related_updates():
aux_rows = query.get_compiler(self.using).execute_sql(result_type)
if is_empty and aux_rows:
rows = aux_rows
is_empty = False
return rows
Я переписал execute_sql следующим образом:
def execute_sql(self, result_type):
"""
Execute the specified update. Return the number of rows affected by
the primary update query. The "primary update query" is the first
non-empty query that is executed. Row counts for any subsequent,
related queries are not available.
"""
cursor = super().execute_sql(result_type)
try:
if cursor:
cursor.execute("select @@rowcount")
rows = cursor.fetchall()[0][0]
else:
rows = 0
is_empty = cursor is None
finally:
if cursor:
cursor.close()
for query in self.query.get_related_updates():
aux_rows = query.get_compiler(self.using).execute_sql(result_type)
if is_empty and aux_rows:
rows = aux_rows
is_empty = False
return rows
и теперь он работает, но я не уверен, есть ли более элегантный способ решить эту проблему, так как теперь мне придется отправлять этот код повсюду. Исходный код на: https://github.com/django/django/blob/main/django/db/models/sql/compiler.py
Я столкнулся с той же проблемой и пришел к той же точке в глубинах django.
В моем случае - проблема была в триггере, настроенном for UPDATE
.
Он должен был возвращать @@ROWCOUNT
в качестве результата, но в моем случае этого не произошло.
Кстати, что я сделал (из-за ограничения на редактирование триггеров) - переопределил метод save
в базовой модели для таких моделей на force_update=True
:
class BaseModel(models.Model):
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if self._state.adding:
super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
else:
try:
super().save(force_insert=force_insert, force_update=True, using=using, update_fields=update_fields)
except DatabaseError as e:
if str(e) == 'Forced update did not affect any rows.':
pass
else:
raise e
class Meta:
managed = False
abstract = True