Найти - Пользователи
Полная версия: Работа с датами.
Начало » Django » Работа с датами.
1
Elaphe
В виде, отображающем календарь, добавляю ссылки для навигации.
Месяц и год передаются в url, выглядящий так:
url(r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.calendar, name='calendar')
Нужно сделать, соответственно, ссылки на предыдущий месяц и на следующий месяц.
Есть ли эффективный способ определить номер предыдущего и следующего месяца? Сейчас я использую такую функцию:
  def find_lase_next_month(year, month):
  	cur_date = datetime.date(year, month, 15)
  	step = datetime.timedelta(days=30)
  	next, prev = cur_date + step, cur_date - step
  	nmonth, nyear = '{:02}'.format(next.month), next.year
  	pmonth, pyear = '{:02}'.format(prev.month), prev.year
  	res = {'nmonth': nmonth, 'nyear': nyear, 'pmonth': pmonth, 'pyear': pyear}
Потом результат выполнения функции передается в render_to_response как контекст.
Но что-то мне подсказывает, что это индусокод должен быть способ проще.
Заранее спасибо за помощь!
FishHook
Что-то готовое наверняка есть в модуле dateutil, но надо ли тащить в проект зависимость ради сокращения кода на три строчки?
Elaphe
Подскажите, пожалуйста, еще по сокращению кода.
Для форм использую CBV. Обработка несколько отличается при создании объекта и его изменении. Поэтому использую два отличающихся класса:
class PetAdd(generic.edit.CreateView):
	form_class = PetForm
	template_name = 'pets/pets_form.html'
	def form_valid(self, form):
		birth_date_ff = form.cleaned_data['form_birth_date']
		if birth_date_ff:
			birth_date_ff = birth_date_ff.split('.')[::-1]
		else:
			birth_date_ff = []
		instance = form.save(commit=False)
		instance.u_name = self.request.user
		a = instance.pet_name
		data = []
		for k in range(3):
			try:
				data.append(birth_date_ff.pop(0))
			except IndexError:
				data.append(None)
		instance.birth_year, instance.birth_month, instance.birth_date = data
		if not instance.pet_name:
			psn = instance.species.__str__()
			uniq, i = False, 0
			while uniq == False:
				i+=1
				pr_pet_name = '%s %s' % (psn, i)
				if not Pets.objects.filter(u_name=self.request.user, pet_name=pr_pet_name).exists():
					instance.pet_name = pr_pet_name
					uniq = True
		instance.save()
		self.object = instance
		return redirect(self.get_success_url())
class PetUpdate(generic.edit.UpdateView):
	form_class = PetForm
	template_name = 'pets/pets_form.html'
	model = Pets
	def get_object(self):
		object = super(PetUpdate, self).get_object()
		if self.request.user == object.u_name:
			return object
		else:
			raise PermissionDenied
	def get_initial(self):
		initial = super(PetUpdate, self).get_initial()
		initial['form_birth_date'] = self.object.form_birth_date
		return initial
	def form_valid(self, form):
		birth_date_ff = form.cleaned_data['form_birth_date']
		if birth_date_ff:
			birth_date_ff = birth_date_ff.split('.')[::-1]
		else:
			birth_date_ff = []
		pet_name_ff = form.cleaned_data['pet_name']
		instance = form.save(commit=False)
		data = []
		for k in range(3):
			try:
				data.append(birth_date_ff.pop(0))
			except IndexError:
				data.append(None)
		instance.birth_year, instance.birth_month, instance.birth_date = data
		if not pet_name_ff:
			psn = instance.species.__str__()
			uniq, i = False, 0
			while uniq == False:
				i+=1
				pr_pet_name = '%s %s' % (psn, i)
				if not Pets.objects.filter(u_name=self.request.user, pet_name=pr_pet_name).exists():
					instance.pet_name = pr_pet_name
					uniq = True
		instance.save()
		self.object = instance
		return redirect(self.get_success_url())
Что делать, чтобы это стало короче? Перенести валидацию в forms.py? Или вообще попытаться переписать код так, чтобы оба события одним классом обрабатывались (возможно ли такое в CBV)?
FishHook
Elaphe
А зачем вы дату так странно храните: отдельно год, отдельно месяц, отдельно день?
Почему не просто датой?
Elaphe
Потому что точная дата рождения известна не всегда, иногда известен только месяц и год или только год. Можно было бы, например, если число неизвестно, автоматом записывать 15-е, но тогда нужно было бы хранить отдельное поле, где указывалось бы - известно точное число или нет. И аналогично для месяца. На мой взгляд, эти два варианта (число, месяц и год в отдельных полях или отдельные поля для того, чтобы отмечать, точно дата известна или нет) не имеют значительной разницы. Мне удобнее просто в трех полях хранить.
FishHook
Ну да ладно, тогда другой вопрос: знакомо ли вам понятие “повторное использование кода”?
Зачем вы совершенно одинаковый кусок кода копируете?
Что делать, чтобы это стало короче?
Ответ крайне очевиден: выделить повторяющийся код в базовую реализацию и использовать механизм наследования.
Вообще ваш метод form_valid спроектирован не очень хорошо. Разбейте его на логические блоки (это называется декомпозиция), каждый из которых решает сугубо одну задачу: работа с датой, работа с Pet, и оформите эти блоки в виде отдельных функций.
Elaphe
Я почему спрашиваю, и в том числе уточняю по поводу того, не вынести ли этот фрагмент в forms.py - на собеседовании специалист посмотрел код и посоветовал вообще уходить от CBV. Уходить от них я не хочу, но идея осуществлять всю проверку формы именно в классе, описывающем форму, мне кажется здравой. То есть не просто написать свой миксин, а именно в forms. А вы как считаете?
Про разбивку функции валидации - понятно, буду делать.
FishHook
Elaphe
специалист посмотрел код и посоветовал вообще уходить от CBV.
В следующий раз такому “специалисту” прям с ноги в грызло.
Elaphe
То есть не просто написать свой миксин, а именно в forms. А вы как считаете?
А на самом деле это не имеет особой разницы, потому что формы крайне редко используются более чем в одном-двух представлениях. Поэтому не играет особой роли, где именно вы логику формы опишите, дело вкуса.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB