Skip to content

Commit 43e5309

Browse files
committed
added python 3 and uuid entity id support
1 parent 983416c commit 43e5309

18 files changed

+265
-44
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
*.sqlite*
66
_build
77
build
8+
django_eav.egg-info/*
9+
*.DS_Store
10+
env/
11+
.idea/

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ django-eav
55
Introduction
66
------------
77

8+
89
django-eav provides an Entity-Attribute-Value storage model for django apps.
910

1011
For a decent explanation of what an Entity-Attribute-Value storage model is,

docs/index.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ For example::
139139

140140
eav.register(MyModel, MyEavConfigClass)
141141

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

143146
Using Attributes
144147
================
@@ -151,7 +154,7 @@ First, let's create some attributes::
151154

152155
>>> Attribute.objects.create(name='Weight', datatype=Attribute.TYPE_FLOAT)
153156
>>> Attribute.objects.create(name='Height', datatype=Attribute.TYPE_INT)
154-
>>> Attribute.objects.create(name='Is pregant?', datatype=Attribute.TYPE_BOOLEAN)
157+
>>> Attribute.objects.create(name='Is pregnant?', datatype=Attribute.TYPE_BOOLEAN)
155158

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

eav/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ def get_version():
2727
__version__ = get_version()
2828

2929
def register(model_cls, config_cls=None):
30-
from registry import Registry
30+
from .registry import Registry
3131
Registry.register(model_cls, config_cls)
3232

3333
def unregister(model_cls):
34-
from registry import Registry
34+
from .registry import Registry
3535
Registry.unregister(model_cls)

eav/admin.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
# vim: ai ts=4 sts=4 et sw=4 coding=utf-8
33
#
4-
# This software is derived from EAV-Django originally written and
4+
# This software is derived from EAV-Django originally written and
55
# copyrighted by Andrey Mikhaylenko <http://pypi.python.org/pypi/eav-django>
66
#
77
# This is free software: you can redistribute it and/or modify
@@ -27,8 +27,9 @@
2727

2828
from .models import Attribute, Value, EnumValue, EnumGroup
2929

30+
3031
class BaseEntityAdmin(ModelAdmin):
31-
32+
3233
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
3334
"""
3435
Wrapper for ModelAdmin.render_change_form. Replaces standard static
@@ -93,8 +94,9 @@ def get_fieldsets(self, request, obj=None):
9394

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

97+
9698
class AttributeAdmin(ModelAdmin):
97-
list_display = ('name', 'slug', 'datatype', 'description', 'site')
99+
list_display = ('name', 'content_type', 'slug', 'datatype', 'description', 'site')
98100
list_filter = ['site']
99101
prepopulated_fields = {'slug': ('name',)}
100102

eav/fields.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ def validate(self, value, instance):
8282
:class:`~eav.models.Value` objects.
8383
'''
8484
super(EavDatatypeField, self).validate(value, instance)
85-
from .models import Attribute
8685
if not instance.pk:
8786
return
87+
if type(instance).objects.get(pk=instance.pk).datatype == instance.datatype:
88+
return
8889
if instance.value_set.count():
8990
raise ValidationError(_(u"You cannot change the datatype of an "
9091
u"attribute that is already in use."))

eav/managers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,11 @@ def expand_eav_filter(model_cls, key, value):
110110
return '%s__in' % gr_name, value
111111

112112
try:
113-
field, m, direct, m2m = model_cls._meta.get_field_by_name(fields[0])
113+
field = model_cls._meta.get_field(fields[0])
114114
except models.FieldDoesNotExist:
115115
return key, value
116116

117-
if direct:
117+
if not field.auto_created or field.concrete:
118118
return key, value
119119
else:
120120
sub_key = '__'.join(fields[1:])

eav/migrations/0001_initial.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.10 on 2016-10-13 05:56
3+
from __future__ import unicode_literals
4+
5+
import django.contrib.sites.managers
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
import django.db.models.manager
9+
import django.utils.timezone
10+
import eav.fields
11+
12+
13+
class Migration(migrations.Migration):
14+
15+
initial = True
16+
17+
dependencies = [
18+
('contenttypes', '0002_remove_content_type_name'),
19+
('sites', '0001_initial'),
20+
]
21+
22+
operations = [
23+
migrations.CreateModel(
24+
name='Attribute',
25+
fields=[
26+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27+
('name', models.CharField(help_text='User-friendly attribute name', max_length=100, verbose_name='name')),
28+
('slug', eav.fields.EavSlugField(help_text='Short unique attribute label', verbose_name='slug')),
29+
('description', models.CharField(blank=True, help_text='Short description', max_length=256, null=True, verbose_name='description')),
30+
('type', models.CharField(blank=True, max_length=20, null=True, verbose_name='type')),
31+
('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')),
32+
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
33+
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
34+
('required', models.BooleanField(default=False, verbose_name='required')),
35+
],
36+
options={
37+
'ordering': ['name'],
38+
},
39+
managers=[
40+
('objects', django.db.models.manager.Manager()),
41+
('on_site', django.contrib.sites.managers.CurrentSiteManager()),
42+
],
43+
),
44+
migrations.CreateModel(
45+
name='EnumGroup',
46+
fields=[
47+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
48+
('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
49+
],
50+
),
51+
migrations.CreateModel(
52+
name='EnumValue',
53+
fields=[
54+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
55+
('value', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='value')),
56+
],
57+
),
58+
migrations.CreateModel(
59+
name='Value',
60+
fields=[
61+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
62+
('entity_id', models.IntegerField()),
63+
('value_text', models.TextField(blank=True, null=True)),
64+
('value_float', models.FloatField(blank=True, null=True)),
65+
('value_int', models.IntegerField(blank=True, null=True)),
66+
('value_date', models.DateTimeField(blank=True, null=True)),
67+
('value_bool', models.NullBooleanField()),
68+
('generic_value_id', models.IntegerField(blank=True, null=True)),
69+
('created', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created')),
70+
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
71+
('attribute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eav.Attribute', verbose_name='attribute')),
72+
('entity_ct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='value_entities', to='contenttypes.ContentType')),
73+
('generic_value_ct', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='value_values', to='contenttypes.ContentType')),
74+
('value_enum', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='eav_values', to='eav.EnumValue')),
75+
],
76+
),
77+
migrations.AddField(
78+
model_name='enumgroup',
79+
name='enums',
80+
field=models.ManyToManyField(to='eav.EnumValue', verbose_name='enum group'),
81+
),
82+
migrations.AddField(
83+
model_name='attribute',
84+
name='enum_group',
85+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='eav.EnumGroup', verbose_name='choice group'),
86+
),
87+
migrations.AddField(
88+
model_name='attribute',
89+
name='site',
90+
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='sites.Site', verbose_name='site'),
91+
),
92+
migrations.AlterUniqueTogether(
93+
name='attribute',
94+
unique_together=set([('site', 'slug')]),
95+
),
96+
]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.10 on 2016-10-13 16:57
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('contenttypes', '0002_remove_content_type_name'),
13+
('eav', '0001_initial'),
14+
]
15+
16+
operations = [
17+
migrations.AlterModelOptions(
18+
name='attribute',
19+
options={'ordering': ['content_type', 'name']},
20+
),
21+
migrations.AddField(
22+
model_name='attribute',
23+
name='content_type',
24+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'),
25+
),
26+
migrations.AddField(
27+
model_name='attribute',
28+
name='display_order',
29+
field=models.PositiveIntegerField(default=1, verbose_name='display order'),
30+
),
31+
migrations.AlterUniqueTogether(
32+
name='attribute',
33+
unique_together=set([('site', 'content_type', 'slug')]),
34+
),
35+
]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.3 on 2016-11-04 09:22
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
import eav.fields
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('eav', '0002_auto_20161014_0157'),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='Encounter',
19+
fields=[
20+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21+
('num', models.PositiveSmallIntegerField()),
22+
],
23+
),
24+
migrations.CreateModel(
25+
name='Patient',
26+
fields=[
27+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
28+
('name', models.CharField(max_length=12)),
29+
],
30+
),
31+
migrations.AlterField(
32+
model_name='attribute',
33+
name='datatype',
34+
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'),
35+
),
36+
migrations.AddField(
37+
model_name='encounter',
38+
name='patient',
39+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eav.Patient'),
40+
),
41+
migrations.AddField(
42+
model_name='value',
43+
name='entity_uuid',
44+
field=models.UUIDField(blank=True, null=True),
45+
),
46+
migrations.AlterField(
47+
model_name='value',
48+
name='entity_id',
49+
field=models.IntegerField(blank=True, null=True),
50+
),
51+
]

0 commit comments

Comments
 (0)