Created abstract model to take care of default values

This commit is contained in:
Swen Kooij 2016-10-24 11:50:21 +03:00
parent cdaacdfac5
commit c081b0431d
8 changed files with 136 additions and 75 deletions

View File

@ -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()

View File

@ -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.

View File

@ -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

View 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
View 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

View File

@ -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

View File

@ -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

View 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)