Adding DateTimeField

30 views
Skip to first unread message

Jamie Lawrence

unread,
Jan 6, 2012, 11:04:54 AM1/6/12
to eav-django
Hi all,

I only just picked up this module, and after playing with it enough to
get the demo working, I think I like it. I need a DateTimeField,
however, and am looking for any pitfalls to adding that in. models.py
looks straightforward. That worries me, because there is a lot of
Django magic in there, and I have not spent a lot of time in Djangos
guts.

Also, is there a reason that 'title' for the BaseEntity is a hard-
coded field? That seems wrong.

Andy Mikhaylenko

unread,
Jan 10, 2012, 9:27:02 PM1/10/12
to eav-django
Hi Jamie,

thanks for your interest and sorry for the delay.

> I need a DateTimeField, however, and am looking for any pitfalls
> to adding that in. models.py looks straightforward.
> That worries me, because there is a lot of Django magic in there,
> and I have not spent a lot of time in Djangos guts.

Well, the library is by design a trade-off between the extremes:
fast-but-rigid (normal Django models) and flexible-but-slow (all kinds
of id+JSONField schemata).

(I'm not talking about document-oriented databases here.)

This design, in turn, implies another trade-off: compact-but-limited
vs. universal-but-bloated.

If we go on with adding more and more columns to BaseAttribute,
a) the table will quickly become bloated, and
b) everybody will have to apply migrations over and over again in their
projects, even if the changes are not related to their use cases.

So I'd prefer to freeze BaseAttribute until there's a use case which
cannot be adequately addressed without modifying the BaseAttribute's data
structure.

So, this was an explanation of why there's a DateField but no DateTimeField.

Now, what can be done? Hard to say without knowing your use case, but:

1) if it's very likely that all or most of your entities are going to have the
timestamp, just add a plain DateTimeField to the entity model. EAV can be
perfectly mixed with normal fields.
2) if the former option does not fit you for some reason, I guess you'll need
to add an extra field to Attribute. It *may* be (not tested!) as easy as:

class Schema(BaseSchema):
TYPE_DATETIME = 'datetime'
DATATYPE_CHOICES = BaseSchema.DATATYPE_CHOICES + (
(TYPE_DATETIME, 'date and time'),
)

class Attribute(BaseAttribute):
value_datetime = DateTimeField(blank=True, null=True)
schema = models.ForeignKey(Schema, related_name='attrs')
...

I don't think you'll have to dive into the BaseSchema/BaseAttribute stuff
unless you need a field with more complex behaviour like TYPE_ONE, TYPE_MANY
or TYPE_RANGE.

> Also, is there a reason that 'title' for the BaseEntity is a hard-
> coded field? That seems wrong.

BaseEntity doesn't have one; BaseSchema and BaseChoice do.
This seems pretty reasonable to me.

If you mean Fruit.title from the grocery shop example[1], then again
it makes sense because this attribute is meant to be shared by *all*
objects of this type. It's a demonstration of the 1st solution listed above.

[1] https://bitbucket.org/neithere/eav-django/src/tip/examples/grocery_shop/grocery/models.py#cl-8

Hope this helps.

Cheers,
Andy

Jamie Lawrence

unread,
Jan 11, 2012, 1:36:58 PM1/11/12
to eav-d...@googlegroups.com

On Jan 10, 2012, at 6:27 PM, Andy Mikhaylenko wrote:

> Hi Jamie,

H, Andy!

> thanks for your interest and sorry for the delay.

Thank you for the reply.

>> I need a DateTimeField, however, and am looking for any pitfalls
>> to adding that in. models.py looks straightforward.
>> That worries me, because there is a lot of Django magic in there,
>> and I have not spent a lot of time in Djangos guts.

> This design, in turn, implies another trade-off: compact-but-limited
> vs. universal-but-bloated.
>
> If we go on with adding more and more columns to BaseAttribute,
> a) the table will quickly become bloated, and
> b) everybody will have to apply migrations over and over again in their
> projects, even if the changes are not related to their use cases.

I can certainly understand that. EAV, in general, is not my preferred approach in terms of trade offs, but sometimes one just has to go that route.

> Now, what can be done? Hard to say without knowing your use case, but:

I probably should have described the situation. So, briefly, I'm writing what amounts to a specialized calendar that records a variety of possible different types of events with different characteristics. Most of the events are point-in-time, and so indeed, there is a datetime in the entity. But some of them are begin-end ranges, I experimented with making them separate begin and end events (two rows per event), but in conjunction with the amount of data and the requirement for some fairly hairy filtering, as well as some other design constraints, that turned out to be impractical. (Indeed, this project really is a poor fit for the relational model in general, but the client couldn't be talked into using something else.)

> 2) if the former option does not fit you for some reason, I guess you'll need
> to add an extra field to Attribute. It *may* be (not tested!) as easy as:
>
> class Schema(BaseSchema):
> TYPE_DATETIME = 'datetime'
> DATATYPE_CHOICES = BaseSchema.DATATYPE_CHOICES + (
> (TYPE_DATETIME, 'date and time'),
> )
>
> class Attribute(BaseAttribute):
> value_datetime = DateTimeField(blank=True, null=True)
> schema = models.ForeignKey(Schema, related_name='attrs')

> …

This is more or less what I was thinking, and I'll probably go that route. I appreciate the info.

>> Also, is there a reason that 'title' for the BaseEntity is a hard-
>> coded field? That seems wrong.
>
> BaseEntity doesn't have one; BaseSchema and BaseChoice do.
> This seems pretty reasonable to me.

I went back and read over the code again, and realized I was misunderstanding what was going on. Typical example of too little sleep and too much work.

> Cheers,
> Andy

Thanks again for the info,

-j

Reply all
Reply to author
Forward
0 new messages