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 #893 See merge request bramw/baserow!667
This commit is contained in:
commit
2a23f271a8
5 changed files with 109 additions and 3 deletions
backend
src/baserow/contrib/database
tests/baserow/contrib/database
|
@ -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}
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Reference in a new issue