Форум сайта python.su
Есть представление в CBV
def get_context_data(self, *args, **kwargs): ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs) ctx['special_form'] = SpeciallyPriceForm() return ctx def get(self, request, *args, **kwargs): self.object = None if kwargs.get('slug'): category = Category.objects.filter(slug=kwargs.get('slug')).first() self.initial.update({'category': category}) return self.render_to_response(self.get_context_data()) def post(self, request, *args, **kwargs): self.object = None form = self.get_form() special_form = SpeciallyPriceForm(self.request.POST) print(special_form) if form.is_valid() and special_form.is_valid(): return self.form_valid(form) else: return self.form_invalid(form)
def __init__(self, *args, **kwargs): self.request = kwargs.pop('request') user = self.request.user provider = Provider.objects.filter(user=user.id).last() self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all()) def clean(self): cleaned_data = super(ProductCreateForm, self).clean() cd_category = cleaned_data.get('category')
Офлайн
m0nte-cr1st0
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
special_form = SpeciallyPriceForm(self.request.POST)
Офлайн
FishHook,
FishHookcпасибо, это уже понял, исправил.
У вас request есть в аргументах функции, не нужен тут self
class ProductsCreate(CreateView): model = Product form_class = ProductCreateForm http_method_names = ['get', 'post'] def get_initial(self): initial = super(ProductsCreate, self).get_initial() initial['request'] = self.request return initial def get_context_data(self, *args, **kwargs): ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs) ctx['special_form'] = SpeciallyPriceForm() return ctx def get(self, request, *args, **kwargs): self.object = None if kwargs.get('slug'): category = Category.objects.filter(slug=kwargs.get('slug')).first() self.initial.update({'category': category}) return self.render_to_response(self.get_context_data()) def post(self, request, *args, **kwargs): self.object = None print(request.POST) form = ProductCreateForm(request.POST) special_form = SpeciallyPriceForm(request.POST) if special_form.is_valid(): return self.form_valid(form) else: return self.form_invalid(form)
class ProductCreateForm(forms.ModelForm): #.... def __init__(self, *args, **kwargs): self.request = kwargs.pop('initial').get('request') super(ProductCreateForm, self).__init__(*args, **kwargs) #... user = self.request.user provider = Provider.objects.filter(user=user.id).last() self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all()) #... def clean(self): cleaned_data = super(ProductCreateForm, self).clean() cd_category = cleaned_data.get('category') #... class SpeciallyPriceForm(forms.ModelForm): class Meta: model = SpeciallyPrice fields = ['adittional_specially_price', 'adittional_specially_number']
KeyError at /products/add/
u'initial'
Отредактировано m0nte-cr1st0 (Апрель 2, 2019 15:33:16)
Офлайн
Вроде, разобрался.
Офлайн
Или нет…
Продолжаю бороться с этими формами((
На одной странице есть 2 формы.
Есть 2 модели: 1. Product. 2. SpeciallyPrice. SpeciallyPrice связан через FK с Product. В то же время, SpecialPrice является InlineModel в Product.
Поля формы SpecialPriceForm автоматически создаются суриптом JS. То есть их может быть n-ное колличествоо. Необходимо создать запись для каждого такого срабатывания скрипта. В принципе, я догадываюсь, как это сделать - использовать цикл для списка полученных значений. Но проблема в том, что я не могу получить этот список. По какой-то причине из формы приходит None.
class ProductsCreate(CreateView): model = Product form_class = ProductCreateForm http_method_names = ['get', 'post'] def get_initial(self): initial = super(ProductsCreate, self).get_initial() initial['request'] = self.request return initial def get_context_data(self, *args, **kwargs): ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs) ctx['special_form'] = SpeciallyPriceForm() return ctx def get(self, request, *args, **kwargs): self.object = None if kwargs.get('slug'): category = Category.objects.filter(slug=kwargs.get('slug')).first() self.initial.update({'category': category}) return self.render_to_response(self.get_context_data()) def post(self, request, *args, **kwargs): self.object = None form = ProductCreateForm(request.POST, request.FILES, initial={'request': request}) special_form = SpeciallyPriceForm(request.POST) print(special_form) #Пустая форма, но валидна. Как? if form.is_valid() and special_form.is_valid(): return self.form_valid(form, special_form) else: return self.form_invalid(form, special_form) def form_valid(self, form, special_form): product = form.save(commit=False) product.user = self.request.user product.save() for cat in form.cleaned_data.get('category'): product.category.add(cat) for paym in form.cleaned_data.get('payment_method'): product.payment_method.add(paym) for distr in form.cleaned_data.get('distribution_type'): product.distribution_type.add(distr) #Здесь я думал под каждый элемент списка создавать запись, связанную с созданным продуктом. Верна ли логика? special = special_form.save(commit=False) special.product = product special.save() for spec_price in special_form.cleaned_data.get('adittional_specially_price'): print(spec_price) special.adittional_specially_price = spec_price for spec_numb in special_form.cleaned_data.get('adittional_specially_number'): print(spec_numb) special.adittional_specially_number = spec_numb
class ProductCreateForm(forms.ModelForm): #... class SpeciallyPriceForm(forms.ModelForm): class Meta: model = SpeciallyPrice fields = ['adittional_specially_price', 'adittional_specially_number'] def clean(self): cleaned_data = super(SpeciallyPriceForm, self).clean() cd_adittional_specially_price = cleaned_data.get('adittional_specially_price') print(cd_adittional_specially_price) #None cd_adittional_specially_number = cleaned_data.get('adittional_specially_number') print(cd_adittional_specially_number) #None
<html><body> Special price from {{ special_form.adittional_specially_price }} kg {{ special_form.adittional_specially_number }} usd <script> (function(){ var copy = document.querySelector('.field.inline.specially').cloneNode(true); document.querySelector('html').addEventListener('input', function(e){ if(e.target.classList.contains('event') && e.target.tagName == 'INPUT'){ var error = 0; for(var evt of document.querySelectorAll('.field.inline.specially input.event')){ evt.value = evt.value.replace(/[^\d]/,''); if(!evt.value || +evt.value < 1) error++; } if(!error){ var last = document.querySelectorAll('.field.inline.specially'); last[last.length-1].insertAdjacentHTML('afterEnd', copy.outerHTML); } } }); })(); </script> </body></html>
<label for="specially" class="subhead">Special price from</label> <span class="id_specially_price"><input type="text" name="adittional_specially_price" style="width: 165px" class="event" id="id_adittional_specially_price"></span> <span>kg</span> <span class="id_specially_number"><input type="text" name="adittional_specially_number" style="width: 100px" class="event" id="id_adittional_specially_number"></span> <span>usd</span>
Отредактировано m0nte-cr1st0 (Апрель 3, 2019 01:07:50)
Офлайн
Да, это именно так и есть. Проблему с айди решил. И приходит действительно два последних созданных пустых поля. Как сделать, чтобы приходили все поля, подскажите, пожалуйста.
Офлайн
m0nte-cr1st0
Вы будете дрочиться с формами, формсетами, тупыми CBV, тупым шаблонизатором всю свою дальнейшую карьеру. И не потому что Джанга такая конченая, у других еще хуже. А все потому, что в 2019-м году вы пытаетесь использовать технологии начала 2000-х. Никому эта херомантия давным давно уже не нужна. Начните делать REST-приложения и просветление наступит. Выше вы написали совершенно правильную вещь - это нужно делать с помощью AJAX. Все что вам для этого нужно - только джанговский базовый View (ну или django rest framework). Ну и лучше какой-нибудь клиентский фреймворк.
Вот пример того, как сейчас это делается. Хотелось бы сказать “Забудьте про Джангу”, но нет - если вы только учитесь, все эти шаги пройти надо, но писать полноценное приложение на дефолтной Джанге - это есть кактус.
Офлайн
FishHook
Спасибо за совет. Да, я только изучаю Джанго. И, скорее всего, в будщем, я познаю все технологии, которые помогут решать такие задачи довольно просто. Но, к сожалению, сейчас это моя работа и времени особого у меня разбираться в других технологиях, поэтому и приходится зачастую прибегать к различным костылям и построениям велосипедов. Вот, кстати, в данном случае я заметил, что в запросе POST мне прилетают абсолютно все значения из формы. Вот их-то я и буду дёргать, опираясь чисто на запрос…
Как-то печально всё смотрится, да(
Офлайн
FishHook
да и проект этот довольно бородатый и пытаться переписывать его под что-то новое - себе дороже выйдет.
Офлайн