mirror of
https://github.com/SectorLabs/django-localized-fields.git
synced 2025-09-13 06:53:18 +03:00
Created abstract model to take care of default values
This commit is contained in:
parent
cdaacdfac5
commit
c081b0431d
14
README.rst
14
README.rst
@ -61,15 +61,15 @@ Usage
|
||||
|
||||
Preparation
|
||||
^^^^^^^^^^^
|
||||
Declare fields on your model as ``LocalizedField``:
|
||||
Inherit your model from ``LocalizedModel`` and declare fields on your model as ``LocalizedField``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from localized_fields.models import LocalizedModel
|
||||
from localized_fields.fields import LocalizedField
|
||||
|
||||
|
||||
class MyModel(models.Model):
|
||||
class MyModel(LocalizedModel):
|
||||
title = LocalizedField()
|
||||
|
||||
|
||||
@ -160,11 +160,11 @@ Besides ``LocalizedField``, there's also:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from localized_fields.models import LocalizedModel
|
||||
from localized_fields.fields import (LocalizedField,
|
||||
LocalizedAutoSlugField)
|
||||
|
||||
class MyModel(models.Model):
|
||||
class MyModel(LocalizedModel):
|
||||
title = LocalizedField()
|
||||
slug = LocalizedAutoSlugField(populate_from='title')
|
||||
|
||||
@ -176,10 +176,10 @@ Besides ``LocalizedField``, there's also:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from localized_fields.models import LocalizedModel
|
||||
from localized_fields.fields import (LocalizedField,
|
||||
LocalizedBleachField)
|
||||
|
||||
class MyModel(models.Model):
|
||||
class MyModel(LocalizedModel):
|
||||
title = LocalizedField()
|
||||
description = LocalizedBleachField()
|
||||
|
@ -1,8 +1,10 @@
|
||||
from typing import Callable
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.text import slugify
|
||||
|
||||
from ..forms import LocalizedFieldForm
|
||||
from .localized_field import LocalizedField
|
||||
from .localized_value import LocalizedValue
|
||||
|
||||
@ -28,6 +30,24 @@ class LocalizedAutoSlugField(LocalizedField):
|
||||
|
||||
return name, path, args, kwargs
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
"""Gets the form field associated with this field.
|
||||
|
||||
Because this is a slug field which is automatically
|
||||
populated, it should be hidden from the form.
|
||||
"""
|
||||
|
||||
defaults = {
|
||||
'form_class': LocalizedFieldForm
|
||||
}
|
||||
|
||||
defaults.update(kwargs)
|
||||
|
||||
form_field = super().formfield(**defaults)
|
||||
form_field.widget = forms.HiddenInput()
|
||||
|
||||
return form_field
|
||||
|
||||
def pre_save(self, instance, add: bool):
|
||||
"""Ran just before the model is saved, allows us to built
|
||||
the slug.
|
||||
|
@ -17,9 +17,6 @@ class LocalizedField(HStoreField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initializes a new instance of :see:LocalizedValue."""
|
||||
|
||||
if 'default' not in kwargs:
|
||||
kwargs['default'] = LocalizedValue()
|
||||
|
||||
super(LocalizedField, self).__init__(*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
|
29
localized_fields/models.py
Normal file
29
localized_fields/models.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.db import models
|
||||
|
||||
from .fields import LocalizedField, LocalizedValue
|
||||
|
||||
|
||||
class LocalizedModel(models.Model):
|
||||
"""A model that contains localized fields."""
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initializes a new instance of :see:LocalizedModel.
|
||||
|
||||
Here we set all the fields that are of :see:LocalizedField
|
||||
to an instance of :see:LocalizedValue in case they are none
|
||||
so that the user doesn't explicitely have to do so."""
|
||||
|
||||
super(LocalizedModel, self).__init__(*args, **kwargs)
|
||||
|
||||
for field in self._meta.get_fields():
|
||||
if not isinstance(field, LocalizedField):
|
||||
continue
|
||||
|
||||
value = getattr(self, field.name, None)
|
||||
if not isinstance(value, LocalizedValue):
|
||||
value = LocalizedValue()
|
||||
|
||||
setattr(self, field.name, value)
|
47
tests/fake_model.py
Normal file
47
tests/fake_model.py
Normal file
@ -0,0 +1,47 @@
|
||||
from django.contrib.postgres.operations import HStoreExtension
|
||||
from django.db import connection, migrations
|
||||
from django.db.migrations.executor import MigrationExecutor
|
||||
|
||||
from localized_fields.fields import LocalizedAutoSlugField, LocalizedField
|
||||
from localized_fields.models import LocalizedModel
|
||||
|
||||
MODEL = None
|
||||
|
||||
|
||||
def get_fake_model():
|
||||
"""Creates a fake model to use during unit tests."""
|
||||
|
||||
global MODEL
|
||||
|
||||
if MODEL:
|
||||
return MODEL
|
||||
|
||||
class TestModel(LocalizedModel):
|
||||
"""Model used for testing the :see:LocalizedAutoSlugField."""
|
||||
|
||||
app_label = 'localized_fields'
|
||||
|
||||
title = LocalizedField()
|
||||
slug = LocalizedAutoSlugField(populate_from='title')
|
||||
|
||||
class TestProject:
|
||||
|
||||
def clone(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
class TestMigration(migrations.Migration):
|
||||
operations = [
|
||||
HStoreExtension()
|
||||
]
|
||||
|
||||
with connection.schema_editor() as schema_editor:
|
||||
migration_executor = MigrationExecutor(schema_editor.connection)
|
||||
migration_executor.apply_migration(
|
||||
TestProject(),
|
||||
TestMigration('eh', 'localized_fields')
|
||||
)
|
||||
|
||||
schema_editor.create_model(TestModel)
|
||||
|
||||
MODEL = TestModel
|
||||
return MODEL
|
@ -1,12 +1,10 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.postgres.operations import HStoreExtension
|
||||
from django.db import connection, migrations, models
|
||||
from django.db.migrations.executor import MigrationExecutor
|
||||
from django.test import TestCase
|
||||
from django.utils.text import slugify
|
||||
|
||||
from localized_fields.fields import (LocalizedAutoSlugField, LocalizedField,
|
||||
LocalizedValue)
|
||||
from localized_fields.fields import LocalizedAutoSlugField
|
||||
|
||||
from .fake_model import get_fake_model
|
||||
|
||||
|
||||
class LocalizedAutoSlugFieldTestCase(TestCase):
|
||||
@ -20,39 +18,7 @@ class LocalizedAutoSlugFieldTestCase(TestCase):
|
||||
|
||||
super(LocalizedAutoSlugFieldTestCase, cls).setUpClass()
|
||||
|
||||
class TestModel(models.Model):
|
||||
"""Model used for testing the :see:LocalizedAutoSlugField."""
|
||||
|
||||
app_label = 'localized_fields'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.title = self.title or LocalizedValue()
|
||||
self.slug = self.slug or LocalizedValue()
|
||||
|
||||
title = LocalizedField()
|
||||
slug = LocalizedAutoSlugField(populate_from='title')
|
||||
|
||||
class TestProject:
|
||||
|
||||
def clone(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
class TestMigration(migrations.Migration):
|
||||
operations = [
|
||||
HStoreExtension()
|
||||
]
|
||||
|
||||
with connection.schema_editor() as schema_editor:
|
||||
migration_executor = MigrationExecutor(schema_editor.connection)
|
||||
migration_executor.apply_migration(
|
||||
TestProject(),
|
||||
TestMigration('eh', 'localized_fields')
|
||||
)
|
||||
schema_editor.create_model(TestModel)
|
||||
|
||||
cls.TestModel = TestModel
|
||||
cls.TestModel = get_fake_model()
|
||||
|
||||
def test_populate(self):
|
||||
"""Tests whether the :see:LocalizedAutoSlugField's
|
||||
|
@ -235,33 +235,6 @@ class LocalizedFieldTestCase(TestCase):
|
||||
assert not LocalizedField().clean(None)
|
||||
assert not LocalizedField().clean(['huh'])
|
||||
|
||||
@staticmethod
|
||||
def test_default_value():
|
||||
"""Tests whether the default value is a :see:LocalizedValue
|
||||
instance."""
|
||||
|
||||
field = LocalizedField()
|
||||
|
||||
assert field.default
|
||||
assert isinstance(field.default, LocalizedValue)
|
||||
|
||||
for lang_code, _ in settings.LANGUAGES:
|
||||
assert not field.default.get(lang_code)
|
||||
|
||||
@staticmethod
|
||||
def test_default_value_override():
|
||||
"""Tests whether the default value of a field
|
||||
can correctly be overriden."""
|
||||
|
||||
default_value = LocalizedValue(get_init_values())
|
||||
field = LocalizedField(default=default_value)
|
||||
|
||||
assert field.default
|
||||
assert isinstance(field.default, LocalizedValue)
|
||||
|
||||
for lang_code, _ in settings.LANGUAGES:
|
||||
assert default_value.get(lang_code) == field.default.get(lang_code)
|
||||
|
||||
@staticmethod
|
||||
def test_formfield():
|
||||
"""Tests whether the :see:formfield function
|
||||
|
29
tests/test_localized_model.py
Normal file
29
tests/test_localized_model.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from localized_fields.fields import LocalizedValue
|
||||
|
||||
from .fake_model import get_fake_model
|
||||
|
||||
|
||||
class LocalizedModelTestCase(TestCase):
|
||||
"""Tests whether the :see:LocalizedModel class."""
|
||||
|
||||
TestModel = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creates the test model in the database."""
|
||||
|
||||
super(LocalizedModelTestCase, cls).setUpClass()
|
||||
|
||||
cls.TestModel = get_fake_model()
|
||||
|
||||
@classmethod
|
||||
def test_defaults(cls):
|
||||
"""Tests whether all :see:LocalizedField
|
||||
fields are assigned an empty :see:LocalizedValue
|
||||
instance when the model is instanitiated."""
|
||||
|
||||
obj = cls.TestModel()
|
||||
|
||||
assert isinstance(obj.title, LocalizedValue)
|
Loading…
x
Reference in New Issue
Block a user