簡體   English   中英

在 ModelForm 中僅將日期時間字段顯示為小時和分鍾(不顯示日期)

[英]Displaying datetime field as hours and minutes only (no date displayed) in ModelForm

我正在 Django 上構建日歷。 當用戶點擊日歷上的某一天時,他會被重定向到一個 CreateEventForm,在那里他可以創建在他點擊的那一天 (selected_date) 發生的事件。 為了避免用戶必須輸入他選擇的日期的麻煩,我使用 get_form_kwargs() 將 selected_date 發送到表單並預填充 start_time 和 end-time 字段。 這樣,他只需要輸入事件的開始時間和結束時間的小時和分鍾。

我的問題

目前,整個“%Y-%m-%dT%H:%M”格式顯示如下:

在此處輸入圖片說明

我只想顯示 %H:%M。 但我想確保 datetime 對象仍然包含日期; 除了它不會顯示給最終用戶之外,如下所示:

在此處輸入圖片說明

我嘗試使用表單小部件格式化日期時間對象,但它似乎不起作用。 當我將字段格式化為 '%H:%M' 時,該字段顯示如下:

在此處輸入圖片說明

形式

class EventForm(ModelForm):
  class Meta:
    model = Event
    widgets = {
      'start_time': DateInput(attrs={'type': 'datetime-local'}, format='%H:%M'),
      'end_time': DateInput(attrs={'type': 'datetime-local'}, format='%H:%M'),
    }
    fields = '__all__'

  def __init__(self, selected_date, *args, **kwargs):
    super(EventForm, self).__init__(*args, **kwargs)
    self.fields['start_time'].initial = selected_date
    self.fields['end_time'].initial = selected_date
    self.fields['start_time'].input_formats = ('%H:%M',)
    self.fields['end_time'].input_formats = ('%H:%M',)

楷模

class Event(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

    def get_absolute_url(self):
        return reverse('cal:calendar')

觀看次數

class EventCreateView(generic.CreateView):
    model = Event
    template_name = 'cal/event.html'
    form_class = EventForm

    def get_form_kwargs(self):
        kwargs = super(EventCreateView, self).get_form_kwargs()
        selected_date_str = self.request.GET.get('date', None)
        selected_date = datetime.strptime(selected_date_str, '%Y-%m-%d')
        kwargs.update({'selected_date': selected_date})
        return kwargs

class EventUpdateView(generic.UpdateView):
    model = Event
    template_name = 'cal/event.html'
    form_class = EventForm

模板

{% extends 'cal/base.html' %}
{% load crispy_forms_tags %}

{% block title %}
Event
{% endblock %}

{% block content %}
<div class="clearfix">
  <a class="btn btn-info left" href="{% url 'cal:calendar' %}"> Calendar </a>
</div>
<div class="container">

<form method="post">
  <div class="form-group">
      {% csrf_token %}
      {% if form.instance.pk %}
          <h3 class="center">{{ form.instance.start_time }}</h3>
      {% else %}
          <h3 class="center">{{selected_date}}</h3>
      {% endif %}

      <div class="col-4">{{ form.title | as_crispy_field }}</div>
      <div class="col-4">{{ form.description | as_crispy_field }}</div>
      <div class="col-4">{{ form.start_time | as_crispy_field }}</div>
      <div class="col-4">{{ form.end_time | as_crispy_field }}</div>

      {% if form.instance.pk %}
          <a href="{% url 'cal:event_delete' pk=event.pk %}" class="btn btn-danger"> Delete </a>
      {% endif %}
      <button type="submit" class="btn btn-info"> Submit </button>

</div>

</form>
{% endblock %}
  1. 覆蓋clean方法來處理創建datetime對象
  2. 我很確定你需要一個DateTimeInput小部件
  3. 使用selected_date在表單上添加一個隱藏字段
class EventForm(ModelForm):
    start_time = forms.DateTimeField(required=True, input_formats=['%H:%M'], localize=True, widget=forms.DateTimeInput)
    end_time = forms.DateTimeField(required=True, input_formats=['%H:%M'], localize=True, widget=forms.DateTimeInput)
    selected_date = forms.DateField(required=True)

    class Meta:
        model = Event
        fields = ['title', 'description', 'start_time', 'end_time', 'selected_date']

    def __init__(self, selected_date, *args, **kwargs):
        super(EventForm, self).__init__(*args, **kwargs)
        self.fields['selected_date'].initial = selected_date

    def clean(self):

        end_time = self.cleaned_data['end_time']
        end_time = end_time.replace(year = self.cleaned_data['selected_date'].year)
        end_time = end_time.replace(month = self.cleaned_data['selected_date'].month)
        end_time = end_time.replace(day = self.cleaned_data['selected_date'].day)

        start_time = self.cleaned_data['start_time']
        start_time = start_time.replace(year = self.cleaned_data['selected_date'].year)
        start_time = start_time.replace(month = self.cleaned_data['selected_date'].month)
        start_time = start_time.replace(day = self.cleaned_data['selected_date'].day)

        return self.cleaned_data.update({'end_time': end_time, 'start_time': start_time})

要將selected_date到您的EventCreateView (當用戶從​​您的模板提交表單時會發生這種情況),請將以下內容添加到您的模板中:

<form>
...
    <input id="selected_date" type="hidden" name="selected_date" value="{{ selected_date }}">
...
</form>

與自動從請求中提取titledescription並保存到表單中一樣, selected_date將被 Django 提取。 發生這種情況是因為您使用視圖會自動獲取 POST 數據並將其傳遞給您的表單類 因此, hidden字段中selected_date的值將在您的clean()方法中提供給您,然后我們使用它來創建完整的datetime對象並將它們傳遞回表單框架,該框架將為您保存它們。

可以在此處找到有關隱藏元素的更多信息

注意:這要求您在 POST 請求期間將selected_date傳回,在用戶填寫完end_timestart_time 這是因為如果字符串匹配,Django 的表單框架將自動獲取該值。 (如果您需要幫助,請發布您的模板代碼。)

我的更改依賴於 Django 表單的實現細節。 clean方法狀態的文檔

表單子類的 clean() 方法可以執行需要訪問多個表單字段的驗證。 您可以在此處進行檢查,例如“如果提供了字段 A,則字段 B 必須包含有效的電子郵件地址”。 如果願意,此方法可以返回一個完全不同的字典,它將用作cleaned_data。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM