Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creation Receipt #58

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion dynamic_initial_data/base.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import json

from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.db.transaction import atomic
from django.utils import timezone
from django.utils.module_loading import import_string

from dynamic_initial_data.exceptions import InitialDataCircularDependency, InitialDataMissingApp
from dynamic_initial_data.models import RegisteredForDeletionReceipt
from dynamic_initial_data.models import RegisteredForDeletionReceipt, CreationReceipt


class BaseInitialData(object):
Expand Down Expand Up @@ -33,6 +35,32 @@ def register_for_deletion(self, *model_objs):
"""
self.model_objs_registered_for_deletion.extend(model_objs)

@atomic
def create_once(self, model_class, unique_name, **kwargs):
"""
Ensures that a model with given attributes is only created once. This is ideal for fixture data we want
initially populated within Ambition that can be permanently deleted by customer.

1. First we check for Creation Receipt.
2. If one didn't previously exist then create Model w/ Attributes.
"""

# Get the Content Type
content_type = ContentType.objects.get_for_model(model_class)

# See if receipt exists for given model and attributes, if not then create
receipt, created = CreationReceipt.objects.get_or_create(
unique_name=unique_name,
defaults={
'model_class_type': content_type,
'model_attributes': json.dumps(kwargs)
}
)

# If receipt did not previously exist then go ahead and create model with given attributes
if created:
model_class.objects.create(**kwargs)

def update_initial_data(self, *args, **kwargs):
"""
Raises an error if the subclass does not implement this
Expand Down
24 changes: 24 additions & 0 deletions dynamic_initial_data/migrations/0002_creationreceipt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 2.2.8 on 2020-02-19 20:16

import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('dynamic_initial_data', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='CreationReceipt',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('model_attributes', django.contrib.postgres.fields.jsonb.JSONField()),
('model_class_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
),
]
7 changes: 7 additions & 0 deletions dynamic_initial_data/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import JSONField
from django.db import models
from manager_utils import ManagerUtilsManager

Expand All @@ -22,3 +23,9 @@ class RegisteredForDeletionReceipt(models.Model):

class Meta:
unique_together = ('model_obj_type', 'model_obj_id')


class CreationReceipt(models.Model):
name = models.CharField(max_length=256, unique=True)
model_class_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
model_attributes = JSONField()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get_version():
],
license='MIT',
install_requires=[
'Django>=2.0',
'Django>=2.0,<3.0',
'django-manager-utils>=1.4.0',
],
tests_require=[
Expand Down