Home>

I am creating a shift management application, but I can reach it by saving it smoothly the first time, but I can not pass vaild after the second time.

There are no particular errors.
If i skip the POST, it doesn't respond and you can skip to the next page through vaild if the data is deleted.

In the model, association with user and start time, end time, date is the planned date
Is set as. Start and end are choice

SUB_START = (
    ('0', '✕'),
    ('1', '14'),
    ('2', '16'),
    ('3', '17'),
    ('4', '17 .5 '),
    ('5', '18'),
    ('6', '18 .5 '),
    ('7', '19'),
    ('8', '19 .5 '),
    ('9', '20'),
    ('10', '○'),
)
SUB_END = (
    ('0', '✕'),
    ('1', '22'),
    ('2', '23'),
    ('3', '○'),
)
class Schedule (models.Model):
    """Schedule"""
    user = models.ForeignKey (settings.AUTH_USER_MODEL, verbose_name = 'User', on_delete = models.SET_NULL, blank = True, null = True)
    start_time = models.CharField ('start time', choices = SUB_START, max_length = 50, blank = True, default = "0")
    end_time = models.CharField ('End time', choices = SUB_END, max_length = 50, blank = True, default = "0")
    date = models.DateField ('date')
    # created_at = models.DateTimeField ('creation date', default = timezone.now)
    def __int __ (self):
        return self.date

Form hides only date input

forms.py

class SimpleScheduleForm (forms.ModelForm):
    "" "Simple schedule registration form" ""
    class Meta:
        model = Schedule
        fields = ('start_time', 'end_time', 'date')
        widgets = {
            'date': forms.HiddenInput,
        }

1st-15th, 16th-31st
Monthclarendar mixin is making a calendar like this.
Maybe there is no problem so far ...

mixins.py
class MonthCalendarMixin (BaseCalendarMixin):
    "" "Mixin which provides the function of monthly calendar" "" "
    def get_previous_week (self, date):
        if date.month == 1 and date.day == 16:
            return date.replace (year = date.year-1, month = 12, day = 16)
        if date.month == 1 and date.day == 1:
            return date.replace (year = date.year-1, month = 12, day = 1)
        if date.day == 16:return date.replace (month = date.month -1,, day = 16)
        if date.day == 1:
            return date.replace (month = date.month -1,, day = 1)
    def get_week_days (self):
        month = self.kwargs.get ('month')
        year = self.kwargs.get ('year')
        day = self.kwargs.get ('day')
        if month and year and day:
            date = datetime.date (year = int (year), month = int (month), day = int (day))
            if date.month == 12 and date.day>10:
                month = 1
                year = date.year +1
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (1))
                dtlist = [date + datetime.timedelta (days = day) for day in range (0,15)]
                return dtlist
            if date.month == 1 and date.day == 1:
                month = 12
                year = date.year-1
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (15))
                dtlist = [date + datetime.timedelta (days = day) for day in range (1, dtm-14)]
                return dtlist
            if date.month! = 12 and date.day<21 and date.day>4:
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month + 1), day = int (1))
                dtlist = [date + datetime.timedelta (days = day) for day in range (0,15)]
                return dtlist
            if date.day<6:
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (15))
                dtlist = [date + datetime.timedelta (days = day) for day in range (1, dtm-14)]
                return dtlist
            if date.day>20:
                month = month-1
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (15))
                dtlist = [date + datetime.timedelta (days = day) for day in range (1, dtm-14)]
                return dtlist
        else:
            date = datetime.date.today ()
            year = int (date.year)
            month = int (date.month)
            day = int (date.day)
            if date.day<21 and date.day>5:
                date = datetime.date (year = int (year), month = int (month + 1), day = int (1))
                dtlist = [date + datetime.timedelta (days = day) for day in range (0,15)]
                return dtlist
            if date.day<6:
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (15))
                dtlist = [date + datetime.timedelta (days = day) for day in range (1, dtm-14)]
                return dtlist
            if date.day>20:
                month = month + 1
                dtm = calendar.monthrange (year, month) [1]date = datetime.date (year = int (year), month = int (month), day = int (15))
                dtlist = [date + datetime.timedelta (days = day) for day in range (1, dtm-14)]
                return dtlist
            if date.month == 12 and date.day<21 and date.day>5:
                month = 1
                year = date.year +1
                dtm = calendar.monthrange (year, month) [1]
                date = datetime.date (year = int (year), month = int (month), day = int (1))
                dtlist = [date + datetime.timedelta (days = day) for day in range (0,15)]
                return dtlist

    def name (self):
        weekname = ['Mon', 'Tue', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
        name = []
        week = []
        day = self.get_week_days ()
        for l in day:
            name.append (l.weekday ())
        for nn in name:
            week.append (weekname [nn])
        return week

    def get_month_calendar (self):
        self.setup_calendar ()
        days = self.get_week_days ()
        first = days [0]
        last = days [-1]
        ago = self.get_previous_week (first)
        calendar_data = {
            'now': datetime.date.today (),
            'month_days': days,
            'month_previous': ago,
            'month_next': first,
            'week_names': self.name (),
        }
        return calendar_data

class MonthWithFormsMixin (MonthCalendarMixin):
    def get_month_forms (self, start, end, days):
        lookup = {
            '{} __ range'.format (self.date_field): (start, end),
            'user__pk': self.kwargs.get ('user_pk'),
        }
        queryset = self.model.objects.filter (** lookup)
        days_count = len (days)
        FormClass = forms.modelformset_factory (self.model, self.form_class, extra = days_count)
        if self.request.method == 'POST':
            formset = self.month_formset = FormClass (self.request.POST or None)
        else:
            formset = self.month_formset = FormClass (queryset = queryset)
        day_forms = {day: [] for day in days}
        dates = []
        for bound_form in formset.initial_forms:
            instance = bound_form.instance
            date = getattr (instance, self.date_field)
            dates.append (date)for empty_form, (d, empty_list) in zip (formset.extra_forms, day_forms.items ()):
            if d in dates:
                pass
            else:
                date = d
                empty_form.initial = {self.date_field: date}
                empty_list.append (empty_form)
        for bound_form in formset.initial_forms:
            instance = bound_form.instance
            date = getattr (instance, self.date_field)
            day_forms [date] .append (bound_form)
        return [{key: day_forms [key] for key in itertools.islice (day_forms, 0, days_count)}]
    def get_month_calendar (self):
        calendar_context = super (). get_month_calendar ()
        month_days = calendar_context ['month_days']
        month_first = month_days [0]
        month_last = month_days [-1]
        calendar_context ['month_day_forms'] = self.get_month_forms (
            month_first,
            month_last,
            month_days
        )
        calendar_context ['month_formset'] = self.month_formset
        return calendar_context
views.py
class MonthWithFormsCalendar (mixins.MonthWithFormsMixin, generic.View):
    template_name = 'app/month_with_forms.html'
    model = Schedule
    date_field = 'date'
    form_class = SimpleScheduleForm
    def get (self, request, ** kwargs):
        print (1)
        context = self.get_month_calendar ()
        context ['user'] = get_object_or_404 (User, pk = self.kwargs ['user_pk'])
        return render (request, self.template_name, context)

    def post (self, request, ** kwargs):
        print (2)
        context = self.get_month_calendar ()
        user_pk = self.kwargs ['user_pk']
        user = get_object_or_404 (User, pk = user_pk)
        context ['user'] = user
        formset = context ['month_formset']
        print (formset)
        if formset.is_valid ():
            print (1)
            instances = formset.save (commit = False)
            for schedule in instances:
                schedule.user = user
                schedule.save ()
            return redirect ('app: week_with_schedule', user_pk = user_pk)
        return render (request, self.template_name, context)
  • Answer # 1

    solved.

    class MonthWithFormsMixin (MonthCalendarMixin):
        def get_month_forms (self, start, end, days):
            lookup = {
                '{} __ range'.format (self.date_field): (start, end),
                'user__pk': self.kwargs.get ('user_pk'),
            }
            queryset = self.model.objects.filter (** lookup)
            days_count = len (days)
            FormClass = forms.modelformset_factory (self.model, self.form_class, extra = days_count, max_num = days_count)
            if self.request.method == 'POST':
                formset = self.month_formset = FormClass (self.request.POST)
            else:
                formset = self.month_formset = FormClass (queryset = queryset)
            dates = []
            for bound_form in formset.initial_forms:
                instance = bound_form.instance
                date = getattr (instance, self.date_field)
                dates.append (date)
                days.remove (date)
            print (len (dates))
            day_forms = {day: [] for day in days}
            for empty_form, (date, empty_list) in zip (formset.extra_forms, day_forms.items ()):
                empty_form.initial = {self.date_field: date}
                empty_list.append (empty_form)
            for bound_form in formset.initial_forms:
                instance = bound_form.instance
                date = getattr (instance, self.date_field)
                d2 = {date: []}
                d2 [date] .append (bound_form)
                day_forms.update (d2)
            day_forms = sorted (day_forms.items ())
            day_forms = dict (day_forms)
            return [{key: day_forms [key] for key in itertools.islice (day_forms, 0, days_count)}]
        def get_month_calendar (self):
            calendar_context = super (). get_month_calendar ()
            month_days = calendar_context ['month_days']
            month_first = month_days [0]
            month_last = month_days [-1]
            calendar_context ['month_day_forms'] = self.get_month_forms (
                month_first,
                month_last,
                month_days
            )
            calendar_context ['month_formset'] = self.month_formset
            return calendar_context