Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django DateField with only month and year

I post this because I could not find an answer/example that satisfied me and I solved it a way I haven't read in there. Maybe it can be useful or can be discussed.

Basically, my app displays formsets where users can create objects. Once validated, the formset is displayed again and user can add new objects. Specifying a day is not relevant.

I first started to use some javascript to do it, then played with Django custom model (to subclass models.DateField).

I could not succeed to do it with the later (my post updated linked to this one) As I have deadlines, I did it with simple ChoiceField storing objects as Integers and then, use a @property method to build a proper date out of those user inputs (add 1 as day).

This way I avoided to deep dive in Django steam pipes and even got rid of a datepicker!

But thanks to the @property, I can still keep the convenience of formatting dates in Django templates and make date calculation etc...

models.py :

NOTE : make use to return None if the date cannot be built out of filled fields, otherwise you'll have an unbound error when trying to render those @property field in a template.

class MyModel(models.Model):

    YEAR_CHOICES = [(y,y) for y in range(1968, datetime.date.today().year+1)]
    MONTH_CHOICE = [(m,m) for m in range(1,13)]

    start_year = models.IntegerField(choices=YEAR_CHOICES,
                 default=datetime.datetime.now().year,)
    start_month = models.IntegerField(choices=MONTH_CHOICE,
                  default=datetime.datetime.now().month,)
    end_year = models.IntegerField(choices=YEAR_CHOICES,
               default=datetime.datetime.now().year,)
    end_month = models.IntegerField(choices=MONTH_CHOICE,
                default=datetime.datetime.now().month,)

    @property
    def start_date(self):
        if self.start_year and self.start_month:
            return datetime.date(self.start_year, self.start_month, 1)
        elif self.start_year:
            return datetime.date(self.start_year, 12, 31)
        else:
            return None

    @property
    def end_date(self):
        if self.end_year and self.end_month:
            return datetime.date(self.end_year, self.end_month, 1)
        elif self.end_year:
            return datetime.date(self.end_year, 12, 31)
        else:
            return None

forms.py

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        exclude = ("blabla",)

Now, if you want to display a date in a form template, you can use :

{{ form.instance.start_date }}

Hope it helps & Suggestions are welcome!

like image 972
stockersky Avatar asked Sep 04 '18 16:09

stockersky


1 Answers

it was not too clear for me, what are you doing exactly? if you want to show a date string which has only years and month. that would be achieved by using template-filter date and a format e.g: {{ obj.created_at|date:'%y %m' }}.

but if I'm wrong and may you want to have a custom filed in your modelForm to pick a date(which only has year and month) then something like you've already did is the idea, but the code is the matter

like image 91
Mahdi Firouzjah Avatar answered Oct 21 '22 10:10

Mahdi Firouzjah