1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-15 09:34:13 +00:00

Merge branch '893-last-modified-field-cherry-picked' into 'develop'

Fix LastModifiedField for batch update

Closes 

See merge request 
This commit is contained in:
Bram Wiepjes 2022-05-01 18:48:38 +00:00
commit 2a23f271a8
5 changed files with 109 additions and 3 deletions
backend
src/baserow/contrib/database
tests/baserow/contrib/database

View file

@ -80,6 +80,7 @@ from .fields import (
SingleSelectForeignKey,
BaserowExpressionField,
MultipleSelectManyToManyField,
BaserowLastModifiedField,
)
from .handler import FieldHandler
from .models import (
@ -791,6 +792,7 @@ class CreatedOnLastModifiedBaseFieldType(ReadOnlyFieldType, DateFieldType):
"timezone": serializers.ChoiceField(choices=pytz.all_timezones, required=True)
}
source_field_name = None
model_field_class = models.DateTimeField
model_field_kwargs = {}
populate_from_field = None
@ -818,7 +820,7 @@ class CreatedOnLastModifiedBaseFieldType(ReadOnlyFieldType, DateFieldType):
kwargs["null"] = True
kwargs["blank"] = True
kwargs.update(self.model_field_kwargs)
return models.DateTimeField(**kwargs)
return self.model_field_class(**kwargs)
def contains_query(self, field_name, value, model_field, field):
value = value.strip()
@ -917,6 +919,7 @@ class LastModifiedFieldType(CreatedOnLastModifiedBaseFieldType):
type = "last_modified"
model_class = LastModifiedField
source_field_name = "updated_on"
model_field_class = BaserowLastModifiedField
model_field_kwargs = {"auto_now": True}

View file

@ -8,9 +8,14 @@ from django.db.models.fields.related_descriptors import (
)
from django.utils.functional import cached_property
from baserow.contrib.database.formula import BaserowExpression, FormulaHandler
class BaserowLastModifiedField(models.DateTimeField):
requires_refresh_after_update = True
class SingleSelectForwardManyToOneDescriptor(ForwardManyToOneDescriptor):
def get_queryset(self, **hints):
"""

View file

@ -846,6 +846,11 @@ class RowHandler:
rows_relationships = []
for obj in rows_to_update:
# The `updated_on` field is not updated with `bulk_update`,
# so we manually set the value here.
obj.updated_on = model._meta.get_field("updated_on").pre_save(
obj, add=False
)
row_values = rows_by_id[obj.id]
values, manytomany_values = self.extract_manytomany_values(
row_values, model
@ -927,7 +932,7 @@ class RowHandler:
field["name"]
for field in model._field_objects.values()
if not isinstance(model._meta.get_field(field["name"]), ManyToManyField)
]
] + ["updated_on"]
if len(bulk_update_fields) > 0:
model.objects.bulk_update(rows_to_update, bulk_update_fields)

View file

@ -7,7 +7,7 @@ from rest_framework.status import (
HTTP_401_UNAUTHORIZED,
HTTP_404_NOT_FOUND,
)
from freezegun import freeze_time
from baserow.contrib.database.fields.dependencies.handler import FieldDependencyHandler
from baserow.contrib.database.fields.field_cache import FieldCache
from baserow.contrib.database.fields.handler import FieldHandler
@ -1081,6 +1081,62 @@ def test_batch_update_rows(api_client, data_fixture):
assert getattr(row_2, f"field_{text_field.id}") == "yellow"
@pytest.mark.django_db
@pytest.mark.api_rows
def test_batch_update_rows_last_modified_field(api_client, data_fixture):
user, jwt_token = data_fixture.create_user_and_token()
table = data_fixture.create_database_table(user=user)
text_field = data_fixture.create_text_field(
table=table, order=0, name="Color", text_default="white"
)
last_modified_field = data_fixture.create_last_modified_field(
table=table, order=1, date_include_time=True
)
model = table.get_model()
row_1 = model.objects.create()
row_2 = model.objects.create()
url = reverse("api:database:rows:batch", kwargs={"table_id": table.id})
request_body = {
"items": [
{
f"id": row_1.id,
f"field_{text_field.id}": "green",
},
{
f"id": row_2.id,
f"field_{text_field.id}": "yellow",
},
]
}
expected_response_body = {
"items": [
{
f"id": row_1.id,
f"field_{text_field.id}": "green",
f"field_{last_modified_field.id}": "2022-04-18T00:00:00Z",
"order": "1.00000000000000000000",
},
{
f"id": row_2.id,
f"field_{text_field.id}": "yellow",
f"field_{last_modified_field.id}": "2022-04-18T00:00:00Z",
"order": "1.00000000000000000000",
},
]
}
with freeze_time("2022-04-18 00:00:00"):
response = api_client.patch(
url,
request_body,
format="json",
HTTP_AUTHORIZATION=f"JWT {jwt_token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == expected_response_body
@pytest.mark.django_db
@pytest.mark.api_rows
def test_batch_update_rows_different_fields_provided(api_client, data_fixture):

View file

@ -1,5 +1,8 @@
from decimal import Decimal
from unittest.mock import patch
from freezegun import freeze_time
from datetime import datetime
from pytz import UTC
import pytest
from django.core.exceptions import ValidationError
@ -349,6 +352,40 @@ def test_update_row(send_mock, data_fixture):
assert send_mock.call_args[1]["before_return"] == before_send_mock.return_value
@pytest.mark.django_db
def test_create_rows_created_on_and_last_modified(data_fixture):
user = data_fixture.create_user()
table = data_fixture.create_database_table(user=user)
handler = RowHandler()
with freeze_time("2020-01-01 12:00"):
rows = handler.create_rows(user=user, table=table, rows=[{}])
row = rows[0]
assert row.created_on == datetime(2020, 1, 1, 12, 0, tzinfo=UTC)
assert row.updated_on == datetime(2020, 1, 1, 12, 0, tzinfo=UTC)
@pytest.mark.django_db
def test_update_rows_created_on_and_last_modified(data_fixture):
user = data_fixture.create_user()
table = data_fixture.create_database_table(user=user)
field = data_fixture.create_text_field(table=table)
handler = RowHandler()
with freeze_time("2020-01-01 12:00"):
row = table.get_model().objects.create()
with freeze_time("2020-01-02 12:00"):
rows = handler.update_rows(
user=user,
table=table,
rows=[{"id": row.id, f"field_" f"{field.id}": "Test"}],
)
row = rows[0]
assert row.created_on == datetime(2020, 1, 1, 12, 0, tzinfo=UTC)
assert row.updated_on == datetime(2020, 1, 2, 12, 0, tzinfo=UTC)
@pytest.mark.django_db
@patch("baserow.contrib.database.rows.signals.row_updated.send")
@patch("baserow.contrib.database.rows.signals.before_row_update.send")