[PYTHON] [Django] I made a field to enter the date with 4 digit numbers

I was told that I wanted to enter 4 digits

It is a work application that manages the reservation date of Django that I made a long time ago. Python is 2 system because it is an old one. Django is also old and 1.6.

It was compatible with 8-digit input, but ...

Why enter dates with numbers

Like a Date picker It is cool in terms of UI to input the date by clicking with the mouse, It's easy for users to understand, It is quite troublesome if you need to input continuously. Just like everyone loves editors that don't require a mouse.

problem

The default DateField is the keyword argument input_fields Text input is possible by specifying "% Y-% m-% d", "% Y /% m /% d", etc. Entering hyphens and slashes is quite troublesome. If possible, I want to complete it with just the numbers on the numeric keypad. (If you press Enter to move tabs) However, if you specify "% Y% m% d", there is no problem when you enter 8 digits, If there are not enough digits, how much is the year, how much is the month, and how much is the day The actual behavior will be confusing to the user.

If you specify "% m% d", the year is fixed at 1900. And, as with "% Y% m% d", the problem of the boundary between dates remains.

To solve it, you need to change the interpretation of the input value of Field. Actually, it's OK if you override the to_python function of DateField.

First from 8-digit input

For the time being, after confirming that it is an 8-digit number


def to_python(self, value):
    #abridgement
    #Write the code elsewhere at the end
    year_month_day = value[:4], value[4:6] , value[6:]
    result = date(*map(int, year_month_day))
    return result

Just like a date with 4 digits, 2 digits and 2 digits.

Based on that, enter 4 digits

First, clear the boundary problem by narrowing down to only 4-digit numbers.

If it is 4 digits, there is only a date, so roughly Last year, this year, next year There are three possible patterns.

How to decide is important

Isn't it enough for the time being if it is implemented? If you manage the reservation date, you will use the nearest future date.

That's why the keyword argument determines the date selector at initialization. In terms of image

    DateField("Future day", selecter="nearest_fortune")
    DateField("Past day", selecter="nearest_past")
    DateField("Soon", selecter="nearest")

It looks like the above.

In summary, the code is as follows.

class DateField(forms.DateField):

    def __init__(self, *args, **kwargs):

        #The name of the selecter should be wide to some extent
        nearest = ["nearest_selecter", "nearest"]
        fortune = ["nearest_fortune_selecter",
                   "nearest_fortune",
                   "fortune"]
        past = ["nearest_past_selecter",
                "nearest_past",
                "past"]

        #If you don't pop it, it's superclass__init__Get angry with "undefined arguments" when calling
        selecter_name = kwargs.pop("selecter", None)

        #Change the year selection method with the selecter keyword
        if selecter_name in nearest:
            self.selecter = self.nearest_selecter
        if selecter_name in past:
            self.selecter = self.nearest_past_selecter
        if selecter_name in fortune:
            self.selecter = self.nearest_fortune_selecter
        else:
            self.selecter = self.nearest_selecter

        forms.DateField.__init__(self, *args, **kwargs)

    #The one who selects the near past day
    def nearest_past_selecter(self, days):
        today = date.today()
        get_days = lambda d: abs((today - d).days)
        nearest = min(filter(lambda d: d <= today, days), key=get_days)
        return nearest

    #The one who chooses the near future day
    def nearest_fortune_selecter(self, days):
        today = date.today()
        get_days = lambda d: abs((today - d).days)
        nearest = min(filter(lambda d: d >= today, days), key=get_days)
        return nearest

    #The one who chooses the near day
    def nearest_selecter(self, days):
        today = date.today()
        get_days = lambda d: abs((today - d).days)
        nearest = min(days, key=get_days)
        return nearest

    @override
    def to_python(self, value):
        value = value.strip()

        #For 4 digits
        if len(value) == 4 and value.isdigit():
            month, day = int(value[:2]), int(value[2:4])
            today = date.today()
            prev_year = date(today.year - 1, month, day)
            this_year = date(today.year    , month, day)
            next_year = date(today.year + 1, month, day)
            days = [prev_year, this_year, next_year]
            return self.selecter(days)

        #For 8 digits
        elif len(value) == 8 and value.isdigit():
            year_month_day = value[:4], value[4:6] , value[6:]
            result = date(*map(int, year_month_day))
            if result.year < 2000 or result.year > 2100:
                message = u'Enter the year between 2001 and 2099.'
                self.error_messages['invalid'] = message
                raise ValidationError

        else:
            result = forms.DateField.to_python(self, value)

        return result


Recommended Posts

[Django] I made a field to enter the date with 4 digit numbers
I made a WEB application with Django
I tried to discriminate a 6-digit number with a number discrimination application made with python
I failed to install django with pip, so a reminder of the solution
I tried to create a table only with Django
Transit to the update screen with the Django a tag
I made a command to markdown the table clipboard
I just wanted to extract the data of the desired date and time with Django
I made a command to wait for Django to start until the DB is ready
How to test the current time with Go (I made a very thin library)
I made a package to filter time series with python
I made a command to generate a table comment in Django
I made a function to check the model of DCGAN
I can't log in to the admin page with Django3
I made a class to get the analysis result by MeCab in ndarray with python
I made a fortune with Python.
I made a daemon with Python
When writing to a csv file with python, a story that I made a mistake and did not meet the delivery date
I made a program to solve (hint) Saizeriya's spot the difference
I made a library to easily read config files with Python
[Introduction to StyleGAN] I played with "The Life of a Man" ♬
I tried to create a list of prime numbers with python
I wanted to solve the ABC164 A ~ D problem with Python
I made a development environment for Django 3.0 with Docker, Docker-compose, Poetry
I made a command to display a colorful calendar in the terminal
I compared while reading the documentation to use Jinja2 with Django
I made a program that automatically calculates the zodiac with tkinter
Create a REST API to operate dynamodb with the Django REST Framework
A simple RSS reader made with Django
I made a character counter with Python
I made a script to display emoji
I made CORS custom middleware with Django
I made a Hex map with Python
I made a life game with Numpy
I made a stamp generator with GAN
I made a roguelike game with Python
I made a simple blackjack with Python
I made a configuration file with Python
I made a neuron simulator with Python
[Django 2.2] Add a New badge to new posts with a date using a template filter
I made a tool to automatically browse multiple sites with Selenium (Python)
I tried to create a program to convert hexadecimal numbers to decimal numbers with python
I made a kitchen timer to be displayed on the status bar!
I changed the jwt token generator to simplejwt with Django Rest Auth.
I tried to send a registration completion email from Gmail with django.
I made a GAN with Keras, so I made a video of the learning process.
I made a library konoha that switches the tokenizer to a nice feeling
I made a tool to convert Jupyter py to ipynb with VS Code
I made a program to check the size of a file in Python
I made a mistake in fetching the hierarchy with MultiIndex of pandas
I made a function to see the movement of a two-dimensional array (Python)
I made a tool to estimate the execution time of cron (+ PyPI debut)
I made a stamp substitute bot with line
Mathematics memorandum to keep up with the field # 4
The easiest way to get started with Django
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I want to create an API that returns a model with a recursive relationship in the Django REST Framework
I made a GUI application with Python + PyQt5
I made you to express the end of the IP address with L Chika
How to develop a cart app with Django