How to use ModelChoiceField? I whould like to filter the output from a field form.

563 views
Skip to first unread message

Sergei Sokov

unread,
Apr 28, 2020, 3:33:51 AM4/28/20
to Django users

I have some models classes. And some classes have bounding fields with another class. Each class have the field - author. I whould like that for each user the form bounding field shows only those data which was created these authors.

For example:
class “TypeJob” has field “author”.
User Jhon created a TypJob - “Painting”.
User Alex created a TypJob - “Cleaning”.
Class “Order” has bounding field - “name_typ_job”
When Jhon whould like create an order, he opens the form and click “name type job” field, he sees both type job: painting and cleaning.
I whould like that he sees and could choose only “painting”. Because he is it author.


I wrote that

class OrderTestForm(forms.ModelForm):
    class Meta:
        model = Order
    name_job = forms.ModelChoiceField(queryset=None)
    qs = TypJob.objects.filter(author__id=user.id)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name_job'].queryset = qs

But I have

name ‘user’ is not defined

name ‘author__id’ is not defined

Antje Kazimiers

unread,
Apr 28, 2020, 7:11:03 AM4/28/20
to django...@googlegroups.com
qs = TypJob.objects.filter(author__id=user.id)

needs to go inside of the __init__ function. you pass user = request.user as a parameter to OrderTestForm when you instantiate it in your view and can use it then in your init function.
Also you can only filter the id of the author if the author field is a ForeignKey, is it?

Antje

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/178dcdb1-c119-46ef-83c3-95bda19118c8%40googlegroups.com.

hend hend

unread,
Apr 28, 2020, 11:19:01 AM4/28/20
to Django users
user.id надо брать из request объекта в контроллере request.user.id. В том же контроллере метод get_initial() позволяет инициализировать поля формы(указанной в аттрибуте "form_class")контроллера.
Например:
    def get_initial(self):
            # поле category формы будет установлено в результат выборки по ключу
            self.initial["category"] = Category.objects.get(pk=self.c_id)
        return self.initial.copy() # 

Sergei Sokov

unread,
Apr 28, 2020, 11:57:56 AM4/28/20
to Django users
я не совсем понял

    class Meta:
        model = Order
        fields = '__all__'
    name_job = forms.ModelMultipleChoiceField(queryset=None)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        qs = TypJob.objects.filter(author__id=request.user.id)
        self.fields['name_job'].queryset = qs

I have error
'NoneType' object has no attribute '_prefetch_related_lookups'


вторник, 28 апреля 2020 г., 17:19:01 UTC+2 пользователь hend hend написал:

Antje Kazimiers

unread,
Apr 28, 2020, 12:41:25 PM4/28/20
to django...@googlegroups.com

the form doesn't know the request only the view does. how does your view function look like?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

Sergei Sokov

unread,
Apr 28, 2020, 12:56:37 PM4/28/20
to Django users
forms.py
class OrderForm(forms.ModelForm):

   
class Meta:
        model
= Order

    name_job
= forms.ModelMultipleChoiceField(queryset=None)
   
def __init__(self, *args, **kwargs):
       
super().__init__(*args, **kwargs)
        qs
= TypJob.objects.filter(author__id=request.user.id)

views.py
class OrderNewBigPrintView(LoginRequiredMixin, CustomSuccessMessageMixin, CreateView):
    model
= Order
    template_name
= 'new_order_bp.html'
    form_class
= OrderForm
    success_url
= reverse_lazy('orders')
    success_msg
= 'Ok'

models.py
class TypJob(models.Model):
 author
= models.ForeignKey(User, on_delete = models.CASCADE, verbose_name='author', null=True)
 name_job
= models.CharField('name job', max_length=200)


class Order(models.Model):
 author
= models.ForeignKey(User, on_delete = models.CASCADE, verbose_name='author', blank=True, null=True)
 number_order
= models.CharField('number of order', max_length=100)
 date_create
= models.DateTimeField(auto_now=True)
 name
= models.ForeignKey(Customer, on_delete = models.CASCADE, verbose_name='customer', null=True)
 name_order
= models.CharField('name of order', max_length=200)


вторник, 28 апреля 2020 г., 18:41:25 UTC+2 пользователь Antje Kazimiers написал:

the form doesn't know the request only the view does. how does your view function look like?

On 4/28/20 5:57 PM, Sergei Sokov wrote:
я не совсем понял

    class Meta:
        model = Order
        fields = '__all__'
    name_job = forms.ModelMultipleChoiceField(queryset=None)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        qs = TypJob.objects.filter(author__id=request.user.id)
        self.fields['name_job'].queryset = qs

I have error
'NoneType' object has no attribute '_prefetch_related_lookups'


вторник, 28 апреля 2020 г., 17:19:01 UTC+2 пользователь hend hend написал:
user.id надо брать из request объекта в контроллере request.user.id. В том же контроллере метод get_initial() позволяет инициализировать поля формы(указанной в аттрибуте "form_class")контроллера.
Например:
    def get_initial(self):
            # поле category формы будет установлено в результат выборки по ключу
            self.initial["category"] = Category.objects.get(pk=self.c_id)
        return self.initial.copy() # 

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django...@googlegroups.com.

Antje Kazimiers

unread,
Apr 29, 2020, 3:05:14 AM4/29/20
to django...@googlegroups.com

no idea how you do this with a CreateView but with a simple view function you have a request object:

https://docs.djangoproject.com/en/3.0/topics/http/views/#a-simple-view

this thread is about passing a variable into from the view function to a form:

https://groups.google.com/forum/#!searchin/django-users/I$20think$20in$20your$20view$20modulesView()$20%7Csort:date/django-users/AtTDAn-M7_E/V7sx7piSCQAJ

Antje

To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/bbbdf319-812c-40e0-9ebf-235efed46a9d%40googlegroups.com.

hend hend

unread,
Apr 29, 2020, 3:07:41 AM4/29/20
to Django users



class OrderNewBigPrintView(LoginRequiredMixin, CustomSuccessMessageMixin, CreateView):
    model 
= Order
    template_name 
= 'new_order_bp.html'
    form_class 
= OrderForm
    success_url 
= reverse_lazy('orders')
    success_msg 
= 'Ok'

              # get_initial позволяет установить значения полей связанной формы
              def get_initial(self):        
                  self.initial["name_job"] = TypJob.objects.filter(author__id=self.request.user.id)
         # вернуть нужно копию объекта    
                  return self.initial.copy() 

Sergei Sokov

unread,
Apr 29, 2020, 4:12:07 AM4/29/20
to Django users
hend hend  Не работает, но и ошибку не выдает. Что-то нужно передать в класс формы?
It doesn't work. And it doesn't show an error (

class OrderNewBigPrintView(LoginRequiredMixin, CustomSuccessMessageMixin, CreateView):
    model
= Order
    template_name
= 'new_order_bp.html'
    form_class
= OrderForm
    success_url
= reverse_lazy('orders')

    success_msg
= 'Заказ сохранён'

   
def get_initial(self):
       
self.initial['name_job'] = TypJob.objects.filter(author__id=self.request.user.id)

       
return self.initial.copy()


среда, 29 апреля 2020 г., 9:07:41 UTC+2 пользователь hend hend написал:

Sergei Sokov

unread,
Apr 29, 2020, 4:19:41 AM4/29/20
to Django users
please could you see this 

https://ru.stackoverflow.com/questions/594743/forms-modelchoicefield-%d0%9a%d0%b0%d0%ba-%d0%bf%d0%be%d0%bb%d1%83%d1%87%d0%b8%d1%82%d1%8c-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-queryset-name-model-objects-filt

how to write this "form = KommpredForm(request.POST, user=user)"  in views.py?
If I have Class and form_class

среда, 29 апреля 2020 г., 9:07:41 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 29, 2020, 7:54:23 AM4/29/20
to Django users


вторник, 28 апреля 2020 г., 19:56:37 UTC+3 пользователь Sergei Sokov написал:
# Так должно работать вроде.. 
# view
 class OrderNewBigPrintView(LoginRequiredMixin, CustomSuccessMessageMixin, CreateView):
    model = Order
    template_name 
= 'new_order_bp.html'
    form_class 
= OrderForm
    success_url 
= reverse_lazy('orders')
    success_msg 
= 'Ok'

    # this method will pass 'user' as param in kwargs to form __init__()
    def get_form_kwargs(self):
        kwargs = super(OrderNewBigPrintView, self).get_form_kwargs()
        kwargs['user'] =  self.request.user
        return kwargs

# form
class OrderForm(forms.ModelForm):
    
class Meta:
        model 
= Order
    name_job 
= forms.ModelMultipleChoiceField(queryset=None)

    
def __init__(self, *args, **kwargs):
        # get 'user' param from kwargs
        self.user = kwargs.pop('user', None)
        
super().__init__(*args, **kwargs)
        # set 'name_job' queryset
        self.fields['name_job'].queryset = TypJob.objects.filter(author__id=self.user.id)

Sergei Sokov

unread,
Apr 29, 2020, 10:19:41 AM4/29/20
to Django users
hend hend спасибо большое!
Работает!
Но!
Теперь у меня не получается управлять внешним видом полей

Я хочу переопределить класс в форме, но "user" из представления попадает в этот __init__  тоже

     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         #количество строк в поле комментариев
         self.fields['comment'].widget = Textarea(attrs={'rows': 3})
         for field in self.fields:
             self.fields[field].widget.attrs['class'] = 'form-control'


среда, 29 апреля 2020 г., 13:54:23 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 29, 2020, 11:56:10 AM4/29/20
to Django users
Если 'user'  в классе не нужен, можно не вешать его на self. просто вместо 'self.user' используем 'user': в этом случае 'user' просто локальная переменная метода init.
    def __init__(self, *args, **kwargs):
        # get 'user' param from kwargs
        user = kwargs.pop('user', None)
        
super().__init__(*args, **kwargs)
        # set 'name_job' queryset
        self.fields['name_job'].queryset = TypJob.objects.filter(author__id=user.id)

среда, 29 апреля 2020 г., 17:19:41 UTC+3 пользователь Sergei Sokov написал:

Sergei Sokov

unread,
Apr 29, 2020, 12:49:45 PM4/29/20
to Django users
без self такая ошибка

'OrderForm' object has no attribute 'user'

среда, 29 апреля 2020 г., 17:56:10 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 29, 2020, 2:36:00 PM4/29/20
to Django users
Не нужно нигде  в классе формы обращаться к  'self.user'.  

среда, 29 апреля 2020 г., 19:49:45 UTC+3 пользователь Sergei Sokov написал:

Sergei Sokov

unread,
Apr 30, 2020, 4:34:28 AM4/30/20
to Django users
А как тогда?
self.fields['name_job'].queryset = TypJob.objects.filter(author__id=self.user.id)
как тогда фильтр будет работать?

среда, 29 апреля 2020 г., 20:36:00 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 30, 2020, 6:19:35 AM4/30/20
to Django users
Уже приводил вариант без self, хотя и с self должно бы работать нормально, но раз ругается попробуйте без self.
    def __init__(self, *args, **kwargs):
        # get 'user' param from kwargs
        # user without self
        user = kwargs.pop('user', None)
        
super().__init__(*args, **kwargs)
        # set 'name_job' queryset
        # user.id without self
        self.fields['name_job'].queryset = TypJob.objects.filter(author__id=user.id)


четверг, 30 апреля 2020 г., 11:34:28 UTC+3 пользователь Sergei Sokov написал:

Sergei Sokov

unread,
Apr 30, 2020, 8:46:43 AM4/30/20
to Django users
так работает, но если я добавляю вот это для редактирования отображения полей в форме
    def __init__(self, *args, **kwargs):
       
super().__init__(*args, **kwargs)
       
#количество строк в поле комментариев
       
self.fields['comment'].widget = Textarea(attrs={'rows': 3})
       
for field in self.fields:
           
self.fields[field].widget.attrs['class'] = 'form-control'
тогда у меня вот такая ошибка

TypeError at /new-big-print-order

__init__() got an unexpected keyword argument 'user'

Я так понимаю потому что во views.py вот это
def get_form_kwargs(self):
    kwargs
= super(OrderNewBigPrintView, self).get_form_kwargs()
    kwargs
['user'] = self.request.user
   
return kwargs



четверг, 30 апреля 2020 г., 12:19:35 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 30, 2020, 12:14:38 PM4/30/20
to Django users
Не совсем понимаю, это init какого класса...Но можно попробовать так:
    def __init__(self, *args, **kwargs):
        # delete 'user' from kwargs before calling perent init
        user = kwargs.pop('user', None)
        
super().__init__(*args, **kwargs)

        
#количество строк в поле комментариев
        
self.fields['comment'].widget = Textarea(attrs={'rows': 3})
        
for field in self.fields:
            
self.fields[field].widget.attrs['class'] = 'form-control'


четверг, 30 апреля 2020 г., 15:46:43 UTC+3 пользователь Sergei Sokov написал:

Sergei Sokov

unread,
Apr 30, 2020, 1:00:57 PM4/30/20
to Django users
Так перестает работать первоначальная задача

четверг, 30 апреля 2020 г., 18:14:38 UTC+2 пользователь hend hend написал:

hend hend

unread,
Apr 30, 2020, 1:34:04 PM4/30/20
to Django users
Это init какой формы?..контроллер  о котором мы говорим связан с формой  OrderForm насколько я понял..

четверг, 30 апреля 2020 г., 20:00:57 UTC+3 пользователь Sergei Sokov написал:

hend hend

unread,
Apr 30, 2020, 1:51:54 PM4/30/20
to Django users
Кажется я понял, вы влепили два init в класс? А зачем...
    def __init__(self, *args, **kwargs):
        # get 'user' param from kwargs
        user = kwargs.pop('user', None)
        
super().__init__(*args, **kwargs)
        # set class attrs  
        for field in self.fields.values():
             field.widget.attrs['class'] = 'form-control'
        # set 'name_job' queryset
        self.fields['name_job'].queryset = TypJob.objects.filter(author__id=user.id)

четверг, 30 апреля 2020 г., 20:00:57 UTC+3 пользователь Sergei Sokov написал:

Sergei Sokov

unread,
Apr 30, 2020, 2:59:14 PM4/30/20
to Django users
Действительно!!
А я и не заметил.
Благодарю от всего сердца!!!
Это будет слишком нагло с моей стороны, но
можно ли ваш контакт, чтобы вас (или тебя) на прямую спрашивать разные вопросы касаемо джанго, я совсем новичок в этом деле и, например, этот вопрос задавал на разных форумах, но никто мне не смог помочь.
Если нет так нет, я кроме hend hend ничего не знаю из контактов.
Моя почта sokov точка tlt собака гмэйл точка ком

четверг, 30 апреля 2020 г., 19:51:54 UTC+2 пользователь hend hend написал:

Sergei Sokov

unread,
May 1, 2020, 3:59:09 AM5/1/20
to Django users
А не могли бы вы подсказать как вызвать две разные формы, от двух разных классов в models.py, на одной странице?
Нужно передать в контекст views.py две формы, и эти две формы по разному назвать.

class SkladCreateView(LoginRequiredMixin, CustomSuccessMessageMixin, CreateView):
    model = Sklad
    template_name = 'sklad.html'
    form_class = SkladForm
    success_url = reverse_lazy('sklad')
    success_msg = 'Материал сохранён'
    def get_context_data(self, **kwargs):
        kwargs['list_sklad'] = Sklad.objects.all().order_by('material')
        return super().get_context_data(**kwargs)
    # это функция для назначения автора
    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.author = self.request.user
        self.object.save()
        return super().form_valid(form)




четверг, 30 апреля 2020 г., 19:51:54 UTC+2 пользователь hend hend написал:
Reply all
Reply to author
Forward
0 new messages