#python #django
#python #django
Вопрос:
Я пытаюсь создать приложение для календаря и в настоящее время пытаюсь помешать людям сохранять событие, когда они уже заняты в течение этого периода времени. Я считаю, что моя проблема заключается в том, что в ModelForm нет идентификатора пользователя как части объекта формы. как я могу передать идентификатор пользователя, чтобы я мог использовать его для фильтрации с помощью clean().
Я пытался использовать get_form_kwargs(), но, похоже, это не правильный путь.
Пожалуйста, не могли бы вы указать мне правильное направление, как это сделать.
view.py
class CalendarEventAdd(LoginRequiredMixin, CreateView):
model = Event
form_class = EventForm
template_name = 'calendar_create_event_form.html'
success_url = reverse_lazy('calendar_list')
def form_valid(self, form):
form.instance.manage = self.request.user
return super(CalendarEventAdd, self).form_valid(form)
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user
return kwargs
form.py
class EventForm(forms.ModelForm):
class Meta:
model = Event
widgets = {
'start_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
'end_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
}
fields = ['avilibility','start_time','end_time']
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.filter(manage_id=1, end_time__gte=form_start_time, start_time__lte=form_end_time)
if between:
raise forms.ValidationError('Already Calendar entry for this time')
super().clean()
model.py
class Event(models.Model):
avilibility_choices = [
('Avilible', 'Avilible'),
('Busy', 'Busy'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
manage = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
avilibility = models.CharField(max_length=10, choices=avilibility_choices, editable=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
def __str__(self):
return self.avilibility " - " str(self.start_time) " - " str(self.end_time) " - " str(self.id)
def get_absolute_url(self):
return reverse('calendar_event_detail', args=[str(self.id)])
def get_absolute_url_edit(self):
return reverse('calendar_event_detail_update', args=[str(self.id)])
def get_html_url(self):
url = reverse('event_edit', args=(self.id,))
return f'<a href="{url}"> {self.avilibility} </a>'
Ответ №1:
По вашему мнению, вы должны передать первичный ключ пользователя, поэтому:
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user.pk
return kwargs
Вы можете сохранить его в EventForm
объекте:
class EventForm(forms.ModelForm):
def __init__(self, *args, user_id=None, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
self.user_id = user_id
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.exclude(pk=self.instance.pk).filter(
manage_id=self.user_id,
end_time__gte=form_start_time,
start_time__lte=form_end_time
)
if between.exists():
raise forms.ValidationError('Already Calendar entry for this time')
return super().clean()
Объект, который .exclude(pk=self.instance.pk)
вы редактируете, будет исключен, если позже вы решите использовать EventForm
не только для создания, но и для обновления Event
объекта.
В документации рекомендуется использовать
AUTH_USER_MODEL
параметр [Django-doc] вместоget_user_model()
[Django-doc] . Это безопаснее, поскольку, если приложение аутентификации еще не загружено, в настройках все равно можно указать имя модели. Поэтому лучше написать:
from django.conf import settings class Event(models.Model): # … manage = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE )