Если вы работаете с формами, вы должны использовать CreateView или FormView, а не DetailView. Вот пример реализации, который, как видите, немного сложен для новичка в Django:
from django.views.generic import CreateView
class BookDetailView(NeverCacheMixin, CreateView):
form_class = CommentForm
template_name = 'catalog/book_detail.html'
def dispatch(self, request, *args, **kwargs):
book_slug = self.kwargs.get('slug') # url variables are stored in self.kwargs
self.book = get_object_or_404(Book, slug=book_slug) # attach book to your view
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
# context data passed to template
kwargs['book'] = self.book
kwargs['most_recent'] = Book.objects.order_by('-timestamp')[:3]
if request.user.is_anonymous:
user_membership = None
else:
try:
user_membership = Customer.objects.get(user=self.request.user)
except Customer.DoesNotExist:
user_membership = None
kwargs['user_membership'] = user_membership
return super().get_context_data(**kwargs)
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
instance.post = self.book
instance.save()
return redirect(self.book.get_absolute_url())
Можно думать о первом аргументе блока как об аккумуляторе: результат каждого выполнения блока хранится в аккумуляторе и затем передается следующему выполнению блока. В случае кода, показанного выше, Вы принимаете значение по умолчанию аккумулятор, результат, к 0. Каждое выполнение блока добавляет данное число к текущему общему количеству и затем хранит результат назад в аккумулятор. Следующий вызов блока имеет это новое значение, добавляет к нему, хранилища он снова и повторения.
В конце процесса введите, возвращает аккумулятор, который в этом случае является суммой всех значений в массиве, или 10.
Вот другой простой пример для создания хеша из массива объектов, включенных их строковым представлением:
[1,"a",Object.new,:hi].inject({}) do |hash, item|
hash[item.to_s] = item
hash
end
В этом случае мы принимаем значение по умолчанию наш аккумулятор к пустому хешу, затем заполняя его каждый раз, когда блок выполняется. Заметьте, что мы должны возвратить хеш как последнюю строку блока, потому что результат блока будет сохранен назад в аккумуляторе.
Этот код не позволяет возможность не передачи начального значения, но может помочь объяснить, что продолжается.
def incomplete_inject(enumerable, result)
enumerable.each do |item|
result = yield(result, item)
end
result
end
incomplete_inject([1,2,3,4], 0) {|result, item| result + item} # => 10
Введите применяет блок
result + element
к каждому объекту в массиве. Для следующего объекта ("элемент") значение, возвращенное от блока, является "результатом". Путем Вы назвали его (с параметром), "результат" запускается со значения того параметра. Таким образом, эффект складывает элементы.
Код выполняет итерации по этим четырем элементам в массиве и добавляет предыдущий результат к элементу тока:
inject
принимает значение для запуска с ( 0
в Вашем примере), и блок, и это выполняет тот блок однажды для каждого элемента списка.
result + element
). Самый легкий способ объяснить это может состоять в том, чтобы показать, как каждый шаг работает для Вашего примера; это - мнимый набор шагов, показывающих, как этот результат мог быть оценен:
[1, 2, 3, 4].inject(0) { |result, element| result + element }
[2, 3, 4].inject(0 + 1) { |result, element| result + element }
[3, 4].inject((0 + 1) + 2) { |result, element| result + element }
[4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
[].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
(((0 + 1) + 2) + 3) + 4
10
Что они сказали, но примечание также, что необходимо не всегда обеспечивать "начальное значение":
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
совпадает с
[1, 2, 3, 4].inject { |result, element| result + element } # => 10
Попробуйте его, я буду ожидать.
Когда никакой аргумент не передается для введения, первые два элемента передаются в первое повторение. В примере выше, результат равняется 1, и элемент равняется 2 в первый раз вокруг, таким образом, один меньше вызова выполняется к блоку.