diff --git a/.env.example b/.env.example index efc937001..9f3dd3815 100644 --- a/.env.example +++ b/.env.example @@ -12,7 +12,7 @@ export DOMAIN=your.domain.here export OL_URL="https://openlibrary.org" ## Database backend to use. -## Default is postgres, use sqlite is for dev quickstart only (NOT production!!!) +## Default is postgres, sqlite is for dev quickstart only (NOT production!!!) export FEDIREADS_DATABASE_BACKEND=postgres export MEDIA_ROOT="images/" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9cb68f898..cd768e3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,8 @@ /.vscode # sqlite -.db -.db-journal +*.db +*.db-journal # Fedireads .env diff --git a/fedireads/migrations/0001_initial.py b/fedireads/migrations/0001_initial.py index b9036bdf2..214204e3e 100644 --- a/fedireads/migrations/0001_initial.py +++ b/fedireads/migrations/0001_initial.py @@ -1,13 +1,13 @@ -# Generated by Django 3.0.2 on 2020-02-15 20:11 +# Generated by Django 3.0.3 on 2020-02-15 22:15 from django.conf import settings import django.contrib.auth.models import django.contrib.auth.validators -import django.contrib.postgres.fields.jsonb import django.core.validators from django.db import migrations, models import django.db.models.deletion import django.utils.timezone +import fedireads.utils.fields class Migration(migrations.Migration): @@ -62,7 +62,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('uuid', models.CharField(max_length=255, unique=True)), - ('content', django.contrib.postgres.fields.jsonb.JSONField(max_length=5000)), + ('content', fedireads.utils.fields.JSONField(max_length=5000)), ('activity_type', models.CharField(max_length=255)), ('fedireads_type', models.CharField(blank=True, max_length=255, null=True)), ('created_date', models.DateTimeField(auto_now_add=True)), @@ -75,7 +75,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('openlibrary_key', models.CharField(max_length=255)), - ('data', django.contrib.postgres.fields.jsonb.JSONField()), + ('data', fedireads.utils.fields.JSONField()), ('added_date', models.DateTimeField(auto_now_add=True)), ('updated_date', models.DateTimeField(auto_now=True)), ], @@ -86,7 +86,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('activitypub_id', models.CharField(max_length=255)), ('openlibrary_key', models.CharField(max_length=255, unique=True)), - ('data', django.contrib.postgres.fields.jsonb.JSONField()), + ('data', fedireads.utils.fields.JSONField()), ('cover', models.ImageField(blank=True, null=True, upload_to='covers/')), ('added_date', models.DateTimeField(auto_now_add=True)), ('updated_date', models.DateTimeField(auto_now=True)), @@ -122,7 +122,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('status_type', models.CharField(default='Note', max_length=255)), - ('activity', django.contrib.postgres.fields.jsonb.JSONField(max_length=5000, null=True)), + ('activity', fedireads.utils.fields.JSONField(max_length=5000, null=True)), ('content', models.TextField(blank=True, null=True)), ('created_date', models.DateTimeField(auto_now_add=True)), ('updated_date', models.DateTimeField(auto_now=True)), diff --git a/fedireads/models/activity.py b/fedireads/models/activity.py index 30fcbfc07..e922f1f93 100644 --- a/fedireads/models/activity.py +++ b/fedireads/models/activity.py @@ -1,9 +1,9 @@ ''' models for storing different kinds of Activities ''' -from django.contrib.postgres.fields import JSONField from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from model_utils.managers import InheritanceManager +from fedireads.utils.fields import JSONField class Activity(models.Model): ''' basic fields for storing activities ''' diff --git a/fedireads/models/book.py b/fedireads/models/book.py index ccd8d8236..1cd9952cd 100644 --- a/fedireads/models/book.py +++ b/fedireads/models/book.py @@ -3,13 +3,13 @@ from django.db import models from model_utils.managers import InheritanceManager from django.dispatch import receiver from django.contrib.auth.models import AbstractUser -from django.contrib.postgres.fields import JSONField from django.core.exceptions import ValidationError from Crypto import Random from Crypto.PublicKey import RSA import re from fedireads.settings import DOMAIN, OL_URL +from fedireads.utils.fields import JSONField class Shelf(models.Model): activitypub_id = models.CharField(max_length=255) diff --git a/fedireads/settings.py b/fedireads/settings.py index e4e134049..c5cdfd9b4 100644 --- a/fedireads/settings.py +++ b/fedireads/settings.py @@ -70,7 +70,7 @@ WSGI_APPLICATION = 'fedireads.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases -FEDIREADS_DATABASE_BACKEND = env('FEDIREADS_DATABASE', 'postgres') +FEDIREADS_DATABASE_BACKEND = env('FEDIREADS_DATABASE_BACKEND', 'postgres') FEDIREADS_DBS = { 'postgres': { @@ -80,6 +80,10 @@ FEDIREADS_DBS = { 'PASSWORD': 'fedireads', 'HOST': '', 'PORT': 5432 + }, + 'sqlite': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'fedireads.db') } } diff --git a/fedireads/utils/__init__.py b/fedireads/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/fedireads/utils/fields.py b/fedireads/utils/fields.py new file mode 100644 index 000000000..1d6c8a39b --- /dev/null +++ b/fedireads/utils/fields.py @@ -0,0 +1,67 @@ +'''Quick and dirty shim for JSONField and ArrayField compatibility on sqlite. + +For more info and original code, see: +- https://medium.com/@philamersune/using-postgresql-jsonfield-in-sqlite-95ad4ad2e5f1 +- https://gist.github.com/pvsune/2e5f9f9ae356d0bff633d896bc7d168b#file-django-sqlite-fields-py +''' + +import json + +from django.conf import settings +from django.contrib.postgres.fields import ( + JSONField as DjangoJSONField, + ArrayField as DjangoArrayField, +) +from django.db.models import Field + + +class JSONField(DjangoJSONField): + pass + + +class ArrayField(DjangoArrayField): + pass + + +if 'sqlite' in settings.DATABASES['default']['ENGINE']: + class JSONField(Field): + def db_type(self, connection): + return 'text' + + def from_db_value(self, value, expression, connection): + if value is not None: + return self.to_python(value) + return value + + def to_python(self, value): + if value is not None: + try: + return json.loads(value) + except (TypeError, ValueError): + return value + return value + + def get_prep_value(self, value): + if value is not None: + return str(json.dumps(value)) + return value + + def value_to_string(self, obj): + return self.value_from_object(obj) + + + class ArrayField(JSONField): + def __init__(self, base_field, size=None, **kwargs): + """Care for DjangoArrayField's kwargs.""" + self.base_field = base_field + self.size = size + return super().__init__(**kwargs) + + def deconstruct(self): + """Need to create migrations properly.""" + name, path, args, kwargs = super().deconstruct() + kwargs.update({ + 'base_field': self.base_field.clone(), + 'size': self.size, + }) + return name, path, args, kwargs \ No newline at end of file diff --git a/rebuilddb.sh b/rebuilddb.sh index 536288be1..df855cb99 100755 --- a/rebuilddb.sh +++ b/rebuilddb.sh @@ -6,8 +6,16 @@ if [ ! -f .env ]; then cp .env.example .env fi -dropdb fedireads -createdb fedireads +source .env + +if [ $FEDIREADS_DATABASE_BACKEND = 'sqlite' ]; then + rm fedireads.db +else + # assume postgres + dropdb fedireads + createdb fedireads +fi + python manage.py makemigrations fedireads python manage.py migrate