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:support alter relativedelta field on admin #7

Open
wants to merge 2 commits 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
18 changes: 18 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ perform arithmetic on them within the database.
Usage
-----

Setup:

.. code:: python

INSTALLED_APPS = [
'...',
'relativedeltafield',
'...'
]

Using the field is straightforward. You can add the field to your
model like so:

Expand Down Expand Up @@ -79,6 +89,14 @@ sure that after a ``save()``, your fields are both normalized
and validated.


You can also use on admin:

.. code:: python
from django.contrib import admin

admin.site.register(MyModel)


Limitations and pitfalls
------------------------

Expand Down
67 changes: 66 additions & 1 deletion relativedeltafield/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import re

from django.core.exceptions import ValidationError
from django.contrib.admin.options import FORMFIELD_FOR_DBFIELD_DEFAULTS
from django.db import models
from django.forms.widgets import MultiWidget, TimeInput, NumberInput
from django.utils.translation import ugettext_lazy as _
from django import forms

from datetime import timedelta
from datetime import timedelta, time
from dateutil.relativedelta import relativedelta

# This is not quite ISO8601, as it allows the SQL/Postgres extension
Expand Down Expand Up @@ -75,6 +78,61 @@ def format_relativedelta(relativedelta):



class RelativeDetailInput(MultiWidget):
template_name = 'admin/widgets/relativedelta.html'

def __init__(self, attrs=None):
widgets = (
NumberInput(attrs=attrs),
NumberInput(attrs=attrs),
NumberInput(attrs=attrs),
TimeInput(attrs=attrs),
)
super().__init__(widgets)

def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context.update({
'year_label': _('Year'),
'month_label': _('Month'),
'day_label': _('Day'),
'time_label': _('Time'),
})
return context

def decompress(self, value):
if value:
return [value.years, value.months, value.days,
time(hour=value.hours, minute=value.minutes,
second=value.seconds,
microsecond=value.microseconds)]
return [0, 0, 0, time()]


class RelativeDetailFormField(forms.MultiValueField):
def __init__(self, **kwargs):
fields = [
forms.IntegerField(),
forms.IntegerField(),
forms.IntegerField(),
forms.TimeField(),
]
super().__init__(
fields=fields,
require_all_fields=False, **kwargs
)

def compress(self, data_list):
kwargs = {
'years': data_list[0],
'months': data_list[1],
'days': data_list[2],
'hours': data_list[3].hour,
'minutes': data_list[3].minute,
}
return relativedelta(**kwargs).normalized()


class RelativeDeltaField(models.Field):
"""Stores dateutil.relativedelta.relativedelta objects.

Expand Down Expand Up @@ -150,3 +208,10 @@ def convert_relativedeltafield_value(self, value, expression, connection, contex
def value_to_string(self, obj):
val = self.value_from_object(obj)
return '' if val is None else format_relativedelta(val)


FORMFIELD_FOR_DBFIELD_DEFAULTS[RelativeDeltaField] = {
'form_class': RelativeDetailFormField,
'widget': RelativeDetailInput
}

6 changes: 6 additions & 0 deletions relativedeltafield/templates/admin/widgets/relativedelta.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<p>
{{ year_label }}: {% with widget=widget.subwidgets.0 %}{% include widget.template_name %}{% endwith %}
{{ month_label }}: {% with widget=widget.subwidgets.1 %}{% include widget.template_name %}{% endwith %}
{{ day_label }}: {% with widget=widget.subwidgets.2 %}{% include widget.template_name %}{% endwith %}<br>
{{ time_label }}: {% with widget=widget.subwidgets.3 %}{% include widget.template_name %}{% endwith %}
</p>