diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b0398d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,59 @@
+| | | |
+|--------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| :white_check_mark: | **Tests** | [](https://circleci.com/gh/SectorLabs/django-localized-fields/tree/master) |
+| :memo: | **License** | [](http://doge.mit-license.org) |
+| :package: | **PyPi** | [](https://pypi.python.org/pypi/django-localized-fields) |
+| | **Django Versions** | 2.0, 2.1, 2.2 |
+| | **Python Versions** | 3.7, 3.8 |
+| :book: | **Documentation** | [Read The Docs](https://django-localized-fields.readthedocs.io) |
+| :warning: | **Upgrade** | [Upgrade fom v5.x](https://django-localized-fields.readthedocs.io/releases)
+| :checkered_flag: | **Installation** | [Installation Guide](https://django-localized-fields.readthedocs.io/#installation) |
+
+`django-localized-fields` is an implementation of a field class for Django models that allows the field's value to be set in multiple languages. It does this by utilizing the ``hstore`` type (PostgreSQL specific), which is available as `models.HStoreField` since Django 1.10.
+
+---
+
+:warning: **This README is for v6 which is currently under development. See the `v5.x` branch for v5.x.**
+
+---
+
+## Working with the code
+### Prerequisites
+
+* PostgreSQL 10 or newer.
+* Django 2.0 or newer.
+* Python 3.7 or newer.
+
+### Getting started
+
+1. Clone the repository:
+
+ λ git clone https://github.com/SectorLabs/django-localized-fields.git
+
+2. Create a virtual environment:
+
+ λ cd django-localized-fields
+ λ virtualenv env
+ λ source env/bin/activate
+
+3. Create a postgres user for use in tests (skip if your default user is a postgres superuser):
+
+ λ createuser --superuser psqlextra --pwprompt
+ λ export DATABASE_URL=postgres://psqlextra:@localhost/psqlextra
+
+ Hint: if you're using virtualenvwrapper, you might find it beneficial to put
+ the ``export`` line in ``$VIRTUAL_ENV/bin/postactivate`` so that it's always
+ available when using this virtualenv.
+
+4. Install the development/test dependencies:
+
+ λ pip install -r requirements/test.txt
+ λ pip install -r requirements/analysis.txt
+
+5. Run the tests:
+
+ λ tox
+
+7. Auto-format code, sort imports and auto-fix linting errors:
+
+ λ python setup.py fix
diff --git a/README.rst b/README.rst
deleted file mode 100644
index aa3e629..0000000
--- a/README.rst
+++ /dev/null
@@ -1,408 +0,0 @@
-django-localized-fields
-=======================
-
-.. image:: https://circleci.com/gh/SectorLabs/django-localized-fields.svg?style=svg
- :target: https://circleci.com/gh/SectorLabs/django-localized-fields
-
-.. image:: https://img.shields.io/github/license/SectorLabs/django-localized-fields.svg
- :target: https://github.com/SectorLabs/django-localized-fields/blob/master/LICENSE.md
-
-.. image:: https://badge.fury.io/py/django-localized-fields.svg
- :target: https://pypi.python.org/pypi/django-localized-fields
-
-``django-localized-fields`` is an implementation of a field class for Django models that allows the field's value to be set in multiple languages. It does this by utilizing the ``hstore`` type (PostgreSQL specific), which is available as ``models.HStoreField`` since Django 1.10.
-
-This package requires Python 3.7 or newer, Django 2.0 or newer and PostgreSQL 10 or newer.
-
-Contributors
-------------
-
-* `seroy `_
-* `umazalakain `_
-
-Installation
-------------
-1. Install the package from PyPi:
-
- .. code-block:: bash
-
- $ pip install django-localized-fields
-
-2. Add ``localized_fields`` and ``django.contrib.postgres`` to your ``INSTALLED_APPS``:
-
- .. code-block:: bash
-
- INSTALLED_APPS = [
- ...
-
- 'django.contrib.postgres',
- 'localized_fields.apps.LocalizedFieldsConfig'
- ]
-
-3. Set the database engine to ``psqlextra.backend``:
-
- .. code-block:: python
-
- DATABASES = {
- 'default': {
- ...
- 'ENGINE': 'psqlextra.backend'
- }
- }
-
-3. Set ``LANGUAGES` and `LANGUAGE_CODE`` in your settings:
-
- .. code-block:: python
-
- LANGUAGE_CODE = 'en' # default language
- LANGUAGES = (
- ('en', 'English'),
- ('nl', 'Dutch'),
- ('ro', 'Romanian')
- )
-
-
-4. Apply migrations to enable the HStore extension:
-
- .. code-block:: bash
-
- python manage.py migrate
-
-Usage
------
-
-Preparation
-^^^^^^^^^^^
-Declare fields on your model as ``LocalizedField``:
-
-.. code-block:: python
-
- from localized_fields.fields import LocalizedField
-
-
- class MyModel(models.Model):
- title = LocalizedField()
-
-``django-localized-fields`` integrates with Django's i18n system, in order for certain languages to be available you have to correctly configure the ``LANGUAGES`` and ``LANGUAGE_CODE`` settings:
-
-.. code-block:: python
-
- LANGUAGE_CODE = 'en' # default language
- LANGUAGES = (
- ('en', 'English'),
- ('nl', 'Dutch'),
- ('ro', 'Romanian')
- )
-
-All the ``LocalizedField`` you define now will be available in the configured languages.
-
-Basic usage
-^^^^^^^^^^^
-.. code-block:: python
-
- new = MyModel()
- new.title.en = 'english title'
- new.title.nl = 'dutch title'
- new.title.ro = 'romanian title'
- new.save()
-
-By changing the active language you can control which language is presented:
-
-.. code-block:: python
-
- from django.utils import translation
-
- translation.activate('nl')
- print(new.title) # prints 'dutch title'
-
- translation.activate('en')
- print(new.title) # prints 'english title'
-
-Or get it in a specific language:
-
-.. code-block:: python
-
- print(new.title.get('en')) # prints 'english title'
- print(new.title.get('ro')) # prints 'romanian title'
- print(new.title.get()) # whatever language is the primary one
- print(new.title.get('ar', 'haha')) # prints 'haha' if there is no value in arabic
-
-You can also explicitly set a value in a certain language:
-
-.. code-block:: python
-
- new.title.set('en', 'other english title')
- new.title.set('nl', 'other dutch title')
-
- new.title.ro = 'other romanian title'
-
-Constraints
-^^^^^^^^^^^
-
-**Required/Optional**
-
-Constraints are enforced on a database level.
-
-* Optional filling
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(blank=True, null=True, required=False)
-
-* Make translation required for any language
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(blank=False, null=False, required=False)
-
-* Make translation required for specific languages
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(blank=False, null=False, required=['en', 'ro'])
-
-* Make translation required for all languages
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(blank=False, null=False, required=True)
-
-* By default the primary language **required** and the others optional:
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField()
-
-**Uniqueness**
-
-By default the values stored in a ``LocalizedField`` are *not unique*. You can enforce uniqueness for certain languages. This uniqueness constraint is enforced on a database level using a ``UNIQUE INDEX``.
-
-* Enforce uniqueness for one or more languages:
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(uniqueness=['en', 'ro'])
-
-* Enforce uniqueness for **all** languages:
-
- .. code-block:: python
-
- from localized_fields.util import get_language_codes
-
- class MyModel(models.Model):
- title = LocalizedField(uniqueness=get_language_codes())
-
-* Enforce uniqueness for one ore more languages **together** (similar to Django's ``unique_together``):
-
- .. code-block:: python
-
- class MyModel(models.Model):
- title = LocalizedField(uniqueness=[('en', 'ro')])
-
-* Enforce uniqueness for **all** languages **together**:
-
- .. code-block:: python
-
- from localized_fields.util import get_language_codes
-
- class MyModel(models.Model):
- title = LocalizedField(uniqueness=[(*get_language_codes())])
-
-
-Other fields
-^^^^^^^^^^^^
-Besides ``LocalizedField``, there's also:
-
-* ``LocalizedUniqueSlugField``
- Successor of ``LocalizedAutoSlugField`` that fixes concurrency issues and enforces
- uniqueness of slugs on a database level. Usage is the exact same:
-
- .. code-block:: python
-
- from localized_fields.models import LocalizedModel
- from localized_fields.fields import LocalizedField, LocalizedUniqueSlugField
-
- class MyModel(LocalizedModel):
- title = LocalizedField()
- slug = LocalizedUniqueSlugField(populate_from='title')
-
- ``populate_from`` can be:
-
- - The name of a field.
-
- .. code-block:: python
-
- slug = LocalizedUniqueSlugField(populate_from='name', include_time=True)
-
- - A callable.
-
- .. code-block:: python
-
- def generate_slug(instance):
- return instance.title
-
- slug = LocalizedUniqueSlugField(populate_from=generate_slug, include_time=True)
-
- - A tuple of names of fields.
-
- .. code-block:: python
-
- slug = LocalizedUniqueSlugField(populate_from=('name', 'beer') include_time=True)
-
- By setting the option ``include_time=True``
-
- .. code-block:: python
-
- slug = LocalizedUniqueSlugField(populate_from='title', include_time=True)
-
- You can instruct the field to include a part of the current time into
- the resulting slug. This is useful if you're running into a lot of collisions.
-
-* ``LocalizedBleachField``
- Automatically bleaches the content of the field.
-
- * django-bleach
-
- Example usage:
-
- .. code-block:: python
-
- from localized_fields.fields import LocalizedField, LocalizedBleachField
-
- class MyModel(models.Model):
- title = LocalizedField()
- description = LocalizedBleachField()
-
-* ``LocalizedIntegerField``
- This is an experimental field type introduced in version 5.0 and is subject to change. It also has
- some pretty major downsides due to the fact that values are stored as strings and are converted
- back and forth.
-
- Allows storing integers in multiple languages. This works exactly like ``LocalizedField`` except that
- all values must be integers. Do note that values are stored as strings in your database because
- the backing field type is ``hstore``, which only allows storing strings. The ``LocalizedIntegerField``
- takes care of ensuring that all values are integers and converts the stored strings back to integers
- when retrieving them from the database. Do not expect to be able to do queries such as:
-
- .. code-block:: python
-
- MyModel.objects.filter(score__en__gt=1)
-
-
-* ``LocalizedCharField`` and ``LocalizedTextField``
- These fields following the Django convention for string-based fields use the empty string as value for “no data”, not NULL.
- ``LocalizedCharField`` uses ``TextInput`` (````) widget for render.
-
- Example usage:
-
- .. code-block:: python
-
- from localized_fields.fields import LocalizedCharField, LocalizedTextField
-
- class MyModel(models.Model):
- title = LocalizedCharField()
- description = LocalizedTextField()
-
-* ``LocalizedFileField``
- A file-upload field
-
- Parameter ``upload_to`` supports ``lang`` parameter for string formatting or as function argument (in case if ``upload_to`` is callable).
-
- Example usage:
-
- .. code-block:: python
-
- from localized_fields.fields import LocalizedFileField
-
- def my_directory_path(instance, filename, lang):
- # file will be uploaded to MEDIA_ROOT//_
- return '{0}/{0}_{1}'.format(lang, instance.id, filename)
-
- class MyModel(models.Model):
- file1 = LocalizedFileField(upload_to='uploads/{lang}/')
- file2 = LocalizedFileField(upload_to=my_directory_path)
-
- In template you can access to file attributes:
-
- .. code-block:: django
-
- {# For current active language: #}
-
- {{ model.file.url }} {# output file url #}
- {{ model.file.name }} {# output file name #}
-
- {# Or get it in a specific language: #}
-
- {{ model.file.ro.url }} {# output file url for romanian language #}
- {{ model.file.ro.name }} {# output file name for romanian language #}
-
- To get access to file instance for current active language use ``localized`` method:
-
- .. code-block:: python
-
- model.file.localized()
-
-Experimental feature
-^^^^^^^^^^^^^^^^^^^^
-Enables the following experimental features:
- * ``LocalizedField`` will return ``None`` instead of an empty ``LocalizedValue`` if there is no database value.
- * ``LocalizedField`` lookups will lookup by currently active language instead of HStoreField
-
-.. code-block:: python
-
- LOCALIZED_FIELDS_EXPERIMENTAL = True
-
-
-Django Admin Integration
-^^^^^^^^^^^^^^^^^^^^^^^^
-To enable widgets in the admin, you need to inherit from ``LocalizedFieldsAdminMixin``:
-
-.. code-block:: python
-
- from django.contrib import admin
- from myapp.models import MyLocalizedModel
-
- from localized_fields.admin import LocalizedFieldsAdminMixin
-
- class MyLocalizedModelAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
- """Any admin options you need go here"""
-
- admin.site.register(MyLocalizedModel, MyLocalizedModelAdmin)
-
-
-.. image:: ./images/admin-widget.png
- :alt: The appearance of admin widget
-
-
-Frequently asked questions (FAQ)
---------------------------------
-
-1. Does this package work with Python 2?
-
- No. Only Python 3.7 or newer is supported. We're using type hints. These do not work well under older versions of Python.
-
-2. With what Django versions does this package work?
-
- Only Django 2.x or newer is supported. This is because we rely on Django's ``HStoreField`` and template-based widget rendering.
-
-3. Does this package come with support for Django Admin?
-
- Yes. Our custom fields come with a special form that will automatically be used in Django Admin if the field is of ``LocalizedField``.
-
-4. Why should I pick this over any of the other translation packages out there?
-
- You should pick whatever you feel comfortable with. This package stores translations in your database without having to have translation tables. It however only works on PostgreSQL.
-
-5. I am using PostgreSQL <10, can I use this?
-
- No. The ``hstore`` data type was introduced in PostgreSQL 9.6.
-
-6. I am using this package. Can I give you some beer?
-
- Yes! If you're ever in the area of Cluj-Napoca, Romania, swing by :)
diff --git a/setup.py b/setup.py
index 7d30040..89ac527 100644
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,7 @@ def create_command(text, commands):
with open(
- os.path.join(os.path.dirname(__file__), "README.rst"), encoding="utf-8"
+ os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8"
) as readme:
README = readme.read()