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

Feature/add uuid attribute #45

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
_build
build
django_eav.egg-info/*
*.DS_Store
env/
.idea/
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ django-eav
Introduction
------------


django-eav provides an Entity-Attribute-Value storage model for django apps.

For a decent explanation of what an Entity-Attribute-Value storage model is,
Expand Down
5 changes: 4 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ For example::

eav.register(MyModel, MyEavConfigClass)

To override ``entity_id`` to use ``entity_uuid`` for entity relationship with
model add ``EAV_ENTITY_ID_TYPE='uuid'`` to use ``entity_uuid`` (defaults to
int for ``entity_id``)

Using Attributes
================
Expand All @@ -151,7 +154,7 @@ First, let's create some attributes::

>>> Attribute.objects.create(name='Weight', datatype=Attribute.TYPE_FLOAT)
>>> Attribute.objects.create(name='Height', datatype=Attribute.TYPE_INT)
>>> Attribute.objects.create(name='Is pregant?', datatype=Attribute.TYPE_BOOLEAN)
>>> Attribute.objects.create(name='Is pregnant?', datatype=Attribute.TYPE_BOOLEAN)

Now let's create a patient, and set some of these attributes::

Expand Down
2 changes: 2 additions & 0 deletions eav/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from .models import Attribute, Value, EnumValue, EnumGroup


class BaseEntityAdmin(ModelAdmin):

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
Expand Down Expand Up @@ -93,6 +94,7 @@ def get_fieldsets(self, request, obj=None):

return [(None, {'fields': list(form.fields.keys())})]


class AttributeAdmin(ModelAdmin):
list_display = ('name', 'content_type', 'slug', 'datatype', 'description', 'site')
list_filter = ['site']
Expand Down
51 changes: 51 additions & 0 deletions eav/migrations/0003_auto_20161104_0922.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2016-11-04 09:22
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion
import eav.fields


class Migration(migrations.Migration):

dependencies = [
('eav', '0002_auto_20161014_0157'),
]

operations = [
migrations.CreateModel(
name='Encounter',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('num', models.PositiveSmallIntegerField()),
],
),
migrations.CreateModel(
name='Patient',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=12)),
],
),
migrations.AlterField(
model_name='attribute',
name='datatype',
field=eav.fields.EavDatatypeField(choices=[('text', 'Text'), ('float', 'Float'), ('int', 'Integer'), ('date', 'Date'), ('bool', 'True / False'), ('object', 'Django Object'), ('enum', 'Multiple Choice')], max_length=6, verbose_name='data type'),
),
migrations.AddField(
model_name='encounter',
name='patient',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eav.Patient'),
),
migrations.AddField(
model_name='value',
name='entity_uuid',
field=models.UUIDField(blank=True, null=True),
),
migrations.AlterField(
model_name='value',
name='entity_id',
field=models.IntegerField(blank=True, null=True),
),
]
26 changes: 15 additions & 11 deletions eav/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

from .validators import *
from .fields import EavSlugField, EavDatatypeField
from .utils.utilities import Utils


class EnumValue(models.Model):
Expand Down Expand Up @@ -86,7 +87,7 @@ class EnumValue(models.Model):
@python_2_unicode_compatible
def __str__(self):
return self.value


class EnumGroup(models.Model):
'''
Expand Down Expand Up @@ -304,16 +305,15 @@ def save_value(self, entity, value):
Attribute and *entity*, it will delete that :class:`Value` object.
'''
ct = ContentType.objects.get_for_model(entity)
entity_dict = dict(entity_ct=ct,
attribute=self)
entity_dict[Value.entity_id_type] = entity.pk
try:
value_obj = self.value_set.get(entity_ct=ct,
entity_id=entity.pk,
attribute=self)
value_obj = self.value_set.get(**entity_dict)
except Value.DoesNotExist:
if value == None or value == '':
return
value_obj = Value.objects.create(entity_ct=ct,
entity_id=entity.pk,
attribute=self)
value_obj = Value.objects.create(**entity_dict)
if value == None or value == '':
value_obj.delete()
return
Expand Down Expand Up @@ -347,10 +347,13 @@ class Value(models.Model):
<Value: crazy_dev_user - Favorite Drink: "red bull">
'''

entity_id_type = Utils().get_eav_entity_id_type()

entity_ct = models.ForeignKey(ContentType, related_name='value_entities')
entity_id = models.IntegerField()
entity_id = models.IntegerField(blank=True, null=True)
entity_uuid = models.UUIDField(blank=True, null=True)
entity = generic.GenericForeignKey(ct_field='entity_ct',
fk_field='entity_id')
fk_field=entity_id_type)

value_text = models.TextField(blank=True, null=True)
value_float = models.FloatField(blank=True, null=True)
Expand Down Expand Up @@ -521,8 +524,9 @@ def get_values(self):
'''
Get all set :class:`Value` objects for self.model
'''
return Value.objects.filter(entity_ct=self.ct,
entity_id=self.model.pk).select_related()
entiity_filter = dict(entity_ct=self.ct)
entiity_filter[Value.entity_id_type] = self.model.pk
return Value.objects.filter(**entiity_filter).select_related()

def get_all_attribute_slugs(self):
'''
Expand Down
2 changes: 1 addition & 1 deletion eav/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def _attach_generic_relation(self):
gr_name = self.config_cls.generic_relation_attr.lower()
generic_relation = \
generic.GenericRelation(Value,
object_id_field='entity_id',
object_id_field=Value.entity_id_type,
content_type_field='entity_ct',
related_query_name=rel_name)
generic_relation.contribute_to_class(self.model_cls, gr_name)
Expand Down
Empty file added eav/utils/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions eav/utils/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.conf import settings


class Utils(object):
ENTITY_ID_TYPES = {
'uuid': 'entity_uuid',
'int': 'entity_id'
}

def get_eav_entity_id_type(self):
key = getattr(settings, 'EAV_ENTITY_ID_TYPE', 'int')
try:
return self.ENTITY_ID_TYPES[key]
except KeyError:
print('%s not supported, kindly try uuid or int, defaulting to int' % key)
return self.ENTITY_ID_TYPES['int']
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Django==1.10.3
eav-django==1.4.7