Уведомления

Группа в Telegram: @pythonsu

#1 Май 2, 2016 23:16:58

Elaphe
Зарегистрирован: 2015-02-04
Сообщения: 125
Репутация: +  5  -
Профиль   Отправить e-mail  

Работа с датами.

В виде, отображающем календарь, добавляю ссылки для навигации.
Месяц и год передаются в 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 как контекст.
Но что-то мне подсказывает, что это индусокод должен быть способ проще.
Заранее спасибо за помощь!

Отредактировано Elaphe (Май 2, 2016 23:17:26)

Офлайн

#2 Май 3, 2016 07:49:25

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с датами.

Что-то готовое наверняка есть в модуле dateutil, но надо ли тащить в проект зависимость ради сокращения кода на три строчки?



Офлайн

#3 Май 4, 2016 08:43:35

Elaphe
Зарегистрирован: 2015-02-04
Сообщения: 125
Репутация: +  5  -
Профиль   Отправить e-mail  

Работа с датами.

Подскажите, пожалуйста, еще по сокращению кода.
Для форм использую 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)?

Офлайн

#4 Май 4, 2016 09:02:39

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с датами.

Elaphe
А зачем вы дату так странно храните: отдельно год, отдельно месяц, отдельно день?
Почему не просто датой?



Офлайн

#5 Май 4, 2016 09:16:51

Elaphe
Зарегистрирован: 2015-02-04
Сообщения: 125
Репутация: +  5  -
Профиль   Отправить e-mail  

Работа с датами.

Потому что точная дата рождения известна не всегда, иногда известен только месяц и год или только год. Можно было бы, например, если число неизвестно, автоматом записывать 15-е, но тогда нужно было бы хранить отдельное поле, где указывалось бы - известно точное число или нет. И аналогично для месяца. На мой взгляд, эти два варианта (число, месяц и год в отдельных полях или отдельные поля для того, чтобы отмечать, точно дата известна или нет) не имеют значительной разницы. Мне удобнее просто в трех полях хранить.

Офлайн

#6 Май 4, 2016 09:36:30

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с датами.

Ну да ладно, тогда другой вопрос: знакомо ли вам понятие “повторное использование кода”?
Зачем вы совершенно одинаковый кусок кода копируете?

Что делать, чтобы это стало короче?
Ответ крайне очевиден: выделить повторяющийся код в базовую реализацию и использовать механизм наследования.
Вообще ваш метод form_valid спроектирован не очень хорошо. Разбейте его на логические блоки (это называется декомпозиция), каждый из которых решает сугубо одну задачу: работа с датой, работа с Pet, и оформите эти блоки в виде отдельных функций.



Офлайн

#7 Май 4, 2016 16:59:56

Elaphe
Зарегистрирован: 2015-02-04
Сообщения: 125
Репутация: +  5  -
Профиль   Отправить e-mail  

Работа с датами.

Я почему спрашиваю, и в том числе уточняю по поводу того, не вынести ли этот фрагмент в forms.py - на собеседовании специалист посмотрел код и посоветовал вообще уходить от CBV. Уходить от них я не хочу, но идея осуществлять всю проверку формы именно в классе, описывающем форму, мне кажется здравой. То есть не просто написать свой миксин, а именно в forms. А вы как считаете?
Про разбивку функции валидации - понятно, буду делать.

Офлайн

#8 Май 4, 2016 17:10:50

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с датами.

Elaphe
специалист посмотрел код и посоветовал вообще уходить от CBV.
В следующий раз такому “специалисту” прям с ноги в грызло.
Elaphe
То есть не просто написать свой миксин, а именно в forms. А вы как считаете?
А на самом деле это не имеет особой разницы, потому что формы крайне редко используются более чем в одном-двух представлениях. Поэтому не играет особой роли, где именно вы логику формы опишите, дело вкуса.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version