Skip to content

Commit

Permalink
added python 3 and uuid entity id support
Browse files Browse the repository at this point in the history
  • Loading branch information
musamusa committed May 3, 2018
1 parent 983416c commit 43e5309
Show file tree
Hide file tree
Showing 18 changed files with 265 additions and 44 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
*.sqlite*
_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
4 changes: 2 additions & 2 deletions eav/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def get_version():
__version__ = get_version()

def register(model_cls, config_cls=None):
from registry import Registry
from .registry import Registry
Registry.register(model_cls, config_cls)

def unregister(model_cls):
from registry import Registry
from .registry import Registry
Registry.unregister(model_cls)
8 changes: 5 additions & 3 deletions eav/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4 coding=utf-8
#
# This software is derived from EAV-Django originally written and
# This software is derived from EAV-Django originally written and
# copyrighted by Andrey Mikhaylenko <http://pypi.python.org/pypi/eav-django>
#
# This is free software: you can redistribute it and/or modify
Expand All @@ -27,8 +27,9 @@

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):
"""
Wrapper for ModelAdmin.render_change_form. Replaces standard static
Expand Down Expand Up @@ -93,8 +94,9 @@ def get_fieldsets(self, request, obj=None):

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


class AttributeAdmin(ModelAdmin):
list_display = ('name', 'slug', 'datatype', 'description', 'site')
list_display = ('name', 'content_type', 'slug', 'datatype', 'description', 'site')
list_filter = ['site']
prepopulated_fields = {'slug': ('name',)}

Expand Down
3 changes: 2 additions & 1 deletion eav/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ def validate(self, value, instance):
:class:`~eav.models.Value` objects.
'''
super(EavDatatypeField, self).validate(value, instance)
from .models import Attribute
if not instance.pk:
return
if type(instance).objects.get(pk=instance.pk).datatype == instance.datatype:
return
if instance.value_set.count():
raise ValidationError(_(u"You cannot change the datatype of an "
u"attribute that is already in use."))
4 changes: 2 additions & 2 deletions eav/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ def expand_eav_filter(model_cls, key, value):
return '%s__in' % gr_name, value

try:
field, m, direct, m2m = model_cls._meta.get_field_by_name(fields[0])
field = model_cls._meta.get_field(fields[0])
except models.FieldDoesNotExist:
return key, value

if direct:
if not field.auto_created or field.concrete:
return key, value
else:
sub_key = '__'.join(fields[1:])
Expand Down
96 changes: 96 additions & 0 deletions eav/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.10 on 2016-10-13 05:56
from __future__ import unicode_literals

import django.contrib.sites.managers
from django.db import migrations, models
import django.db.models.deletion
import django.db.models.manager
import django.utils.timezone
import eav.fields


class Migration(migrations.Migration):

initial = True

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

operations = [
migrations.CreateModel(
name='Attribute',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='User-friendly attribute name', max_length=100, verbose_name='name')),
('slug', eav.fields.EavSlugField(help_text='Short unique attribute label', verbose_name='slug')),
('description', models.CharField(blank=True, help_text='Short description', max_length=256, null=True, verbose_name='description')),
('type', models.CharField(blank=True, max_length=20, null=True, verbose_name='type')),
('datatype', eav.fields.EavDatatypeField(choices=[(b'text', 'Text'), (b'float', 'Float'), (b'int', 'Integer'), (b'date', 'Date'), (b'bool', 'True / False'), (b'object', 'Django Object'), (b'enum', 'Multiple Choice')], max_length=6, verbose_name='data type')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('required', models.BooleanField(default=False, verbose_name='required')),
],
options={
'ordering': ['name'],
},
managers=[
('objects', django.db.models.manager.Manager()),
('on_site', django.contrib.sites.managers.CurrentSiteManager()),
],
),
migrations.CreateModel(
name='EnumGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
],
),
migrations.CreateModel(
name='EnumValue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='value')),
],
),
migrations.CreateModel(
name='Value',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('entity_id', models.IntegerField()),
('value_text', models.TextField(blank=True, null=True)),
('value_float', models.FloatField(blank=True, null=True)),
('value_int', models.IntegerField(blank=True, null=True)),
('value_date', models.DateTimeField(blank=True, null=True)),
('value_bool', models.NullBooleanField()),
('generic_value_id', models.IntegerField(blank=True, null=True)),
('created', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('attribute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eav.Attribute', verbose_name='attribute')),
('entity_ct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='value_entities', to='contenttypes.ContentType')),
('generic_value_ct', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='value_values', to='contenttypes.ContentType')),
('value_enum', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='eav_values', to='eav.EnumValue')),
],
),
migrations.AddField(
model_name='enumgroup',
name='enums',
field=models.ManyToManyField(to='eav.EnumValue', verbose_name='enum group'),
),
migrations.AddField(
model_name='attribute',
name='enum_group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='eav.EnumGroup', verbose_name='choice group'),
),
migrations.AddField(
model_name='attribute',
name='site',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='sites.Site', verbose_name='site'),
),
migrations.AlterUniqueTogether(
name='attribute',
unique_together=set([('site', 'slug')]),
),
]
35 changes: 35 additions & 0 deletions eav/migrations/0002_auto_20161014_0157.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.10 on 2016-10-13 16:57
from __future__ import unicode_literals

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


class Migration(migrations.Migration):

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

operations = [
migrations.AlterModelOptions(
name='attribute',
options={'ordering': ['content_type', 'name']},
),
migrations.AddField(
model_name='attribute',
name='content_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'),
),
migrations.AddField(
model_name='attribute',
name='display_order',
field=models.PositiveIntegerField(default=1, verbose_name='display order'),
),
migrations.AlterUniqueTogether(
name='attribute',
unique_together=set([('site', 'content_type', 'slug')]),
),
]
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),
),
]
Empty file added eav/migrations/__init__.py
Empty file.
Loading

0 comments on commit 43e5309

Please sign in to comment.