Найти - Пользователи
Полная версия: Не могу обработать форму...
Начало » Django » Не могу обработать форму...
1
m0nte-cr1st0
Есть представление в 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')

Не удаётся обработать форму (ProductCreateForm).
Если в методе post писать form = ProductCreateForm(request.POST), то получаю ошибку, что ключа request нет.

Если оставить form = self.get_form(), то получаю просто шаблон формы, где некоторые значения заданы, а некоторые - нет (особенно в селектах)

Возможно, это связано с тем, что я в методе get_context_data определял request и в __init__ работал c request
Вообще в методе clean я в форме я обрабатываю данные и там всё нормально приходит, но вот в post делаю что-то не то, явно… Подскажите, пожалуйста.
FishHook
m0nte-cr1st0
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
special_form = SpeciallyPriceForm(self.request.POST)

У вас request есть в аргументах функции, не нужен тут self
m0nte-cr1st0
FishHook,
FishHook
У вас request есть в аргументах функции, не нужен тут self
cпасибо, это уже понял, исправил.
Но общей проблемы это так и не решило.

Вот, как пытался исправить.

 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']

В итоге в request.POST мне прилетают все данные из формы (У меня одна форма содержит в себе две формы). Нужно как-то разграничивать их, наверно, иначе форма будет невалидна, я так думаю.
Также прилетает ошибка
KeyError at /products/add/
u'initial'
m0nte-cr1st0
Вроде, разобрался.
m0nte-cr1st0
Или нет…

Продолжаю бороться с этими формами((
На одной странице есть 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>

Когда я пытался посмотреть во views эту форму, получал просто пустаю форму вроде этой. Но почему она валидна, Карл?


 <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>

Может быть, это нужно решать через Ajax, как-то обрабатывать запрос? Или есть какой-то “джанговский” способ?

Как вариант, я думаю, что во views показны только последние два поля, которые остаются пустыми. Но в этом я не уверен. Я тут, кстати, ещё заметил, что айдишник у созданных полей у инпутов повторяются. Возможно, в этом и есть баг…
m0nte-cr1st0
Да, это именно так и есть. Проблему с айди решил. И приходит действительно два последних созданных пустых поля. Как сделать, чтобы приходили все поля, подскажите, пожалуйста.
FishHook
m0nte-cr1st0
Вы будете дрочиться с формами, формсетами, тупыми CBV, тупым шаблонизатором всю свою дальнейшую карьеру. И не потому что Джанга такая конченая, у других еще хуже. А все потому, что в 2019-м году вы пытаетесь использовать технологии начала 2000-х. Никому эта херомантия давным давно уже не нужна. Начните делать REST-приложения и просветление наступит. Выше вы написали совершенно правильную вещь - это нужно делать с помощью AJAX. Все что вам для этого нужно - только джанговский базовый View (ну или django rest framework). Ну и лучше какой-нибудь клиентский фреймворк.
Вот пример того, как сейчас это делается. Хотелось бы сказать “Забудьте про Джангу”, но нет - если вы только учитесь, все эти шаги пройти надо, но писать полноценное приложение на дефолтной Джанге - это есть кактус.
m0nte-cr1st0
FishHook
Спасибо за совет. Да, я только изучаю Джанго. И, скорее всего, в будщем, я познаю все технологии, которые помогут решать такие задачи довольно просто. Но, к сожалению, сейчас это моя работа и времени особого у меня разбираться в других технологиях, поэтому и приходится зачастую прибегать к различным костылям и построениям велосипедов. Вот, кстати, в данном случае я заметил, что в запросе POST мне прилетают абсолютно все значения из формы. Вот их-то я и буду дёргать, опираясь чисто на запрос…
Как-то печально всё смотрится, да(
m0nte-cr1st0
FishHook
да и проект этот довольно бородатый и пытаться переписывать его под что-то новое - себе дороже выйдет.
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