Support attribute per model and attributes ordering

This commit is contained in:
Hamdi Sahloul 2016-10-14 01:59:07 +09:00
parent f29f4ab2c3
commit 464a947548
4 changed files with 55 additions and 12 deletions

View file

@ -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
@ -28,7 +28,7 @@ from django.utils.safestring import mark_safe
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
@ -94,7 +94,7 @@ class BaseEntityInline(InlineModelAdmin):
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',)}

View file

@ -82,9 +82,10 @@ class EavDatatypeField(models.CharField):
: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."))

View file

@ -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')]),
),
]

View file

@ -152,8 +152,8 @@ class Attribute(models.Model):
'''
class Meta:
ordering = ['name']
unique_together = ('site', 'slug')
ordering = ['content_type', 'name']
unique_together = ('site', 'content_type', 'slug')
TYPE_TEXT = 'text'
TYPE_FLOAT = 'float'
@ -176,6 +176,10 @@ class Attribute(models.Model):
name = models.CharField(_(u"name"), max_length=100,
help_text=_(u"User-friendly attribute name"))
content_type = models.ForeignKey(ContentType,
blank=True, null=True,
verbose_name=_(u"content type"))
site = models.ForeignKey(Site, verbose_name=_(u"site"),
default=settings.SITE_ID)
@ -205,6 +209,8 @@ class Attribute(models.Model):
required = models.BooleanField(_(u"required"), default=False)
display_order = models.PositiveIntegerField(_(u"display order"), default=1)
objects = models.Manager()
on_site = CurrentSiteManager()
@ -312,7 +318,7 @@ class Attribute(models.Model):
value_obj.save()
def __unicode__(self):
return u"%s (%s)" % (self.name, self.get_datatype_display())
return u"%s.%s (%s)" % (self.content_type, self.name, self.get_datatype_display())
class Value(models.Model):
@ -442,18 +448,19 @@ class Entity(object):
Return a query set of all :class:`Attribute` objects that can be set
for this entity.
'''
return self.model._eav_config_cls.get_attributes()
return self.model._eav_config_cls.get_attributes().filter(
models.Q(content_type__isnull=True) | models.Q(content_type=self.ct)).order_by('display_order')
def _hasattr(self, attribute_slug):
'''
Since we override __getattr__ with a backdown to the database, this exists as a way of
Since we override __getattr__ with a backdown to the database, this exists as a way of
checking whether a user has set a real attribute on ourselves, without going to the db if not
'''
return attribute_slug in self.__dict__
def _getattr(self, attribute_slug):
'''
Since we override __getattr__ with a backdown to the database, this exists as a way of
Since we override __getattr__ with a backdown to the database, this exists as a way of
getting the value a user set for one of our attributes, without going to the db to check
'''
return self.__dict__[attribute_slug]
@ -482,7 +489,7 @@ class Entity(object):
value = self._getattr(attribute.slug)
else:
value = values_dict.get(attribute.slug, None)
if value is None:
if attribute.required:
raise ValidationError(_(u"%(attr)s EAV field cannot " \
@ -495,7 +502,7 @@ class Entity(object):
raise ValidationError(_(u"%(attr)s EAV field %(err)s") % \
{'attr': attribute.slug,
'err': e})
def get_values_dict(self):
values_dict = dict()
for value in self.get_values():