Django ModelChoseField limited to current logged user - django

I wrote in forms.py this code
id_group = forms.ModelChoiceField(queryset=StudentsGroup.objects.filter(id_teacher=1))
How change 1 to current logged user?
I try do this User.objects.get(username=request.user.get_username()) but do not work

You will need to pass the current user to the from when you initialize it in the view: form = MyForm(user=request.user), then you can do something like the following in your form:
class MyForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(MyForm, self).__init__(*args, **kwargs)
groups = StudentsGroup.objects.filter(id_teacher=self.user.pk)
self.fields['id_group'].queryset = groups

Related

initialize modelform fields with url parameters in cbv

I have a cbv create view that displays a modelform.
I want to preselect a foreignkey field which is displayed as select choice field.
My problem is that kwargs.get('building_id') in modelform returns None
class VlanCreateForm(ModelForm):
class Meta:
model = Vlan
fields = ['number','description','network','building']
def __init__(self, *args, **kwargs):
building_id = kwargs.get('building_id')
super().__init__(*args, **kwargs)
self.fields['building'].initial = building_id
building is a foreign key to buildings. If I put a constant like self.fields['building'].initial = 1 it is working
class VlanCreateView(CreateView):
model = Vlan
form_class = VlanCreateForm
and the url is
vlan/building/<int:building_id>/create
so I call it like
vlan/building/1/create
You'll need to define the building id in get_form_kwargs
class VlanCreateView(CreateView):
...
building_id=None
def dispatch(self, request, *args, **kwargs):
# Retrieves the building id from url
self.building_id=kwargs.get("building_id")
return super().dispatch(request, *args, **kwargs)
def get_form_kwargs(self, *args, **kwargs):
kwargs=super().get_form_kwargs(*args, **kwargs)
## Sends building id to the form
kwargs["building_id"]=self.building_id
return kwargs
class VlanCreateForm(ModelForm):
class Meta:
model = Vlan
fields = ['number','description','network','building']
def __init__(self, *args, **kwargs):
self.building_id = kwargs.get('building_id')
super().__init__(*args, **kwargs)
self.fields['building'].initial = self.building_id
def post_url(self):
return reverse('app_name:url_name',kwargs={'cg_id':self.building_id} )
In form post action use this post_url for submit form.
then you got the building_id in your view kwargs

Django: How to get user id on forms.py?

I would like to get the current logged in user id in my forms.py. I want to get the id of logged in user.
I am trying to query like this :
class ProcessForm(forms.ModelForm):
company_objective = CompanyObjectives.objects.get(user_rel_objectives=request.user.id)
I get an error NameError: name 'request' is not defined. This makes sense but I have no idea how to get the id here. Plz, advise.
I did this :
in the view i have this:
user = request.user.id form = ProcessForm(user=request.user)
and in the form i have this :
> def __init__(self, *args, **kwargs):
> user = kwargs.pop('user', None)
> super(ProcessForm, self).__init__(*args, **kwargs)
> company_objective = CompanyObjectives.objects.get(user_rel_objectives=user.id)
> print (company_objective.cost_reduction)
I did it like this...
views.py
context['form'] = ProcessForm(user=request.user.id)
forms.py
class ProcessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ProcessForm, self).__init__(*args, **kwargs)
self.fields['company_objective'] = CompanyObjectives.objects.get(user_rel_objectives=user)

How to load a form with options from a queryset in Django

I am trying to load a form with user payment options, so this is needing a query set from the users profile.
I have tried initializing the form (below code) with user being required. The issue is if I make self.options when I am initializing. I have also tried creating the choice_field
class ListPaymentOptionsForm(forms.Form):
choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=options)
def __init__(self, user, *args, **kwargs):
self.options = list(UserPaymentOption.objects
.values_list('last_four', 'last_four')
.filter(user=user, active=True))
super(ListPaymentOptionsForm, self).__init__(self, *args, **kwargs)
The above code gives this error:
choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=options)
NameError: name 'options' is not defined
Then I have tried adding the options on the view instead like this
form = ListPaymentOptionsForm(user=request.user)
form.fields['choice_field'].choices = list(UserPaymentOption.objects
.values_list('id', 'last_four')
.filter(user=request.user, active=True))
This causes an error with the form being used on post, it seems like because it is trying to validate the value provided is a choice but in the actual form the choice is not set. The reason I believe this is the problem is this is what the form returns as
form=ListPaymentOptionsForm(request.POST)
print(form)
This returns: Choice field:Select a valid choice. 54 is not one of the available choices.
Any input on this would be very appreciated. Thanks.
Nearly there!
Try doing the fields['choice_field'].choices in the constructor.
class ListPaymentOptionsForm(forms.Form):
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs) # assuming python 3 constructor
self.options = list(UserPaymentOption.objects.values_list('last_four', 'last_four').filter(user=user, active=True))
self.fields['choice_field'] = forms.ChoiceField(widget=forms.RadioSelect, choices=self.options)
Maybe consider having a look at ModelChoiceField instead however, that way you can specify a queryset instead of having to worry about creating a list:
class ListPaymentOptionsForm(forms.Form):
choice_field = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=UserPaymentOption.objects.none())
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['choice_field'].queryset = UserPaymentOption.objects.filter(user=user, active=True)
EDIT based on comments we can use the kwargs to pass the user which may be better:
class ListPaymentOptionsForm(forms.Form):
choice_field = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=UserPaymentOption.objects.none())
def __init__(self, *args, **kwargs):
user = kwargs.pop('user') # this must be done before super()
super().__init__(*args, **kwargs)
self.fields['choice_field'].queryset = UserPaymentOption.objects.filter(user=user, active=True)
Then instantiate the form to handle POST data:
form = ListPaymentOptionsForm(request.POST, user=user)

Django class based views - Filter queryset and save it

I have two Models named Sponsor and Event and they are something like that:
class Sponsor(models.Model):
name = models.CharField(max_length=200)
user = models.ForeignKey(User)
class Event(models.Model):
name = models.CharField(max_length=200)
sponsor = models.ForeignKey(Sponsor)
Then, I'm using class based views to Update my Object, and is something like that:
class EventUpdate(UpdateView):
model = Event
form_class = EventForm
success_url = reverse_lazy('dashboard_events')
def get_form_kwargs(self):
kwargs = super(EventUpdate, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
Everything is fine so far! If I don't change my EventForm, my UpdateView works pretty well. The only problem is that I have to change my Form and filter my "sponsor" queryset before render it! That's because the user only can see the "sponsors" that he has created.
So, that's what I'm trying to achieve:
class EventForm(ModelForm):
...
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(EventForm, self).__init__(*args, **kwargs)
choices = Sponsor.objects.filter(user=self.user).values_list('pk', 'name')
self.fields['sponsor'] = forms.ChoiceField(choices=choices)
My view is redering right, only sponsors that the user has created, BUT, when I try to save, I get this error:
"Cannot assign "u'2'": "Event.sponsor" must be a "Sponsor" instance."
What should I do? I have no clue how to solve this... Am I following the right logic here? Thanks!
You're on the right track. Try something like this:
class EventForm(ModelForm):
...
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(EventForm, self).__init__(*args, **kwargs)
self.fields['sponsor'].queryset = Sponsor.objects.filter(user=self.user)

Django forms request.user

I my model users can create rifles and this rifle is obviously associated with a User.
class Gun(ImageModel):
user = models.ForeignKey(User)
...
...
...
I have another model which is dependent on this and need to make use of the users rifles, but when the user adds a record I only want to display his rifles.
mt model looks as follows
class Trophies(ImageModel):
used_his = models.ForeignKey(Gun)
my form looks as follows
from django.forms import ModelForm
from django import forms
from models import Trophies
from gunsafe.models import Gun
from django.contrib.auth.models import User
class TrophiesForm(request.user, ModelForm):
used_his = forms.ModelMultipleChoiceField(queryset=Gun.objects.filter(user__id=1))
def __init__(self, user, *args, **kwargs):
super(TrophiesForm, self).__init__(*args, **kwargs)
self.fields['used_his'].queryset = User.objects.filter(pk = user)
I was wondering how I can get the current logged in users ID instead of the user__id=1
Here is the view.
def edit(request, trophy_id, template_name='trophies/edit.html'):
trophy = Trophies.objects.get(pk=trophy_id)
if request.method == 'POST':
form = TrophiesForm(request.POST, request.FILES, instance=trophy)
if form.is_valid():
newform = form.save(commit=False)
newform.user = request.user
newform.save()
...
...
I think you can achieve this by overriding the __init__() method of the form, passing in an instance of User and filtering the queryset using that user. Something like this:
class TrophiesForm(ModelForm):
used_his = forms.ModelMultipleChoiceField(queryset=Gun.objects.filter(user__id=1))
def __init__(self, user, *args, **kwargs):
super(TrophiesForm, self).__init__(*args, **kwargs)
self.fields['used_his'].queryset = User.objects.filter(pk = user.id)
In your view you can pass in the appropriate (currently logged in) instance of User.
def my_trophies(request, *args, **kwargs):
user = request.user
form = TrophiesForm(user)
...
Another angle to Manoj's submission ...
use a kwarg to pass user data, as to not mess with the method signature since it expects request.POST as the first argument. A better convention would be as follows.
class TrophiesForm(ModelForm):
def __init__(self, *args, **kwargs):
#using kwargs
user = kwargs.pop('user', None)
super(TrophiesForm, self).__init__(*args, **kwargs)
self.fields['used_his'].queryset = User.objects.filter(pk = user.id)
Now in the call, this is more explicit and follows a better signature convention
form = TrophiesForm(request.POST, request.FILES, user=request.user)
You could also use instance: (note the super before you grab the instance obj)
class TrophiesForm(ModelForm):
def __init__(self, *args, **kwargs):
super(SubmissionUploadForm, self).__init__(*args, **kwargs)
user = self.instance.user
self.fields['used_his'].queryset = User.objects.filter(pk = user.id)
You can then call in your views.py like so:
form = TrophiesForm(instance=*MyModel*(user=request.user))