TypeError at /risk/riskset
get_context_data() missing 1 required positional argument: 'request'.
See code here:
models.py
class RiskSet(models.Model):
name = models.CharField('Risk set', max_length=500, blank=True, default = '')
owner = models.ForeignKey(User, verbose_name = 'owner', on_delete=models.PROTECT, null=True)
risk = models.ForeignKey(Risk, verbose_name = 'risk', on_delete=models.PROTECT, null = True)
parent_risk_set = models.ForeignKey('self', related_name="child_risk_set", on_delete=models.PROTECT, blank=True, null=True)
def __str__(self):
return "{}".format(self.name)
forms.py
class RiskSetForm(forms.ModelForm):
RiskID1 = forms.ModelMultipleChoiceField(queryset=Risk.objects.all(), required=True,
widget=forms.SelectMultiple(attrs={'class': 'select2'}),
label = 'Risk id')
def __init__(self, *args, **kwargs):
super(RiskSetForm, self).__init__(*args, **kwargs)
print(self)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
class Meta:
model = RiskSet
fields = ['name', 'owner', 'risk', 'parent_risk_set']
views.py
class RiskSet(FormView, SingleTableMixin):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
def get_context_data(self, request):
form = RiskSetForm(request.POST or None)
if form.is_valid():
form.save()
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context
Now I get the error:
TypeError at /risk/riskset
get_context_data() missing 1 required positional argument: 'request'
Please help!
get_context_data does not work with a request parameter. You can pass an arbitrary number of parameters, but here your get_context_data will only run if it is called with the request. You access the request with self.request:
class RiskSet(SingleTableMixin, FormView):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
def get_context_data(self, *args, **kwargs):
form = RiskSetForm(self.request.POST or None)
if form.is_valid():
form.save()
# Call the base implementation first to get a context
context = super().get_context_data(*args, **kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context
Furthermore it makes no sense to do this in the get_context_data method. A FormView has routines in place for this. It You can probably also work with a CreateView which will remove more boilerplate code, like:
from django.views.generic import CreateView
class RiskSet(SingleTableMixin, CreateView):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
success_url = 'path-to-url-when-form-is-valid'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context
Related
In forms, I am trying to filter marketplace drop down field that belong to the logged in user based on its group. Its listing all the dropdown field items. I tried below but I think something is wrong with the filter part.
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user=self.user)
class Meta:
model = Infringement
class Meta:
ordering = ['-updated', '-created']
def __str__(self):
return self.name
fields = ['name', 'link', 'infringer', 'player', 'remove', 'status',
'screenshot','marketplace']
models.py
class Marketplace (models.Model):
name = models.CharField(max_length=100)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
groups = models.ForeignKey(Group, on_delete=models.CASCADE,default=1)
Try this inside __init__() method:
def __init__(self, user, *args, **kwargs):
self.user = user
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset = Marketplace.objects.filter(groups__user=self.user)
final answer is adding self.user = user in the forms and adding user in the view.
forms.py
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
self.user = user
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user=self.user)
class Meta:
model = Infringement
fields = ['name', 'link', 'infringer', 'player', 'remove', 'status',
'screenshot', 'marketplace']
views.py
#login_required(login_url='login')
def createInfringement(request):
user=request.user
form = InfringementForm(user=request.user)
if request.method == 'POST':
form = InfringementForm(user, request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home') context ={'form': form} return render (request, 'base/infringement_form.html', context)
Try this solution...
Basically groups is foreign key in Marketplace model it returns a full object of the Group model.
you tried to filter with the full object it's not possible in a query, so you can filter using id of the user instance
Code becomes like this
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user__id=self.user.id)
class Meta:
model = Infringement
I have the following error:
CompareFormTransporterCompany.__init__() missing 1 required positional argument: 'request'
Here is my form in forms.py:
class CompareFormTransporterCompany(forms.ModelForm):
file = forms.FileField(label="File (CSV, XLSX, XML) ", required=True)
name_transporter = forms.ModelChoiceField(label='Choose transporter', required=True, queryset=Transporter.objects.all())
class Meta:
model = CheckFile
fields = ['file',]
def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request
def clean(self):
super().clean()
uploaded = parse_csv(self.request.FILES['file'])
In views.py:
class ResultFormView(FormView):
""" View to show results of comparison between two files. """
template_name = 'tool/upload.html'
form_class = CompareFormTransporterCompany
success_url = reverse_lazy('tool:result')
And my model in models.py if needed:
class CheckFile(models.Model):
name = models.CharField(max_length=200, blank=True)
month = models.DateField(blank=True, null=True)
timestamp = models.DateTimeField(blank=True, null=True)
profile = models.CharField('Choix du profil', blank=False, choices=PROFILE_CHOICES, max_length=100, default="Client")
file = models.FileField(blank=True, null=True, upload_to="uploads/", validators=[validate_file_extension])
def __str__(self):
return self.name
class Meta:
verbose_name = "file"
verbose_name_plural = "files"
I have been trying a lot of different solutions but I don't understand the error. Could you please help me?
Thought it came from my form but it came from views.py. I have:
class RequestFormMixin:
"""Mixin to inject the request in the form."""
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["request"] = self.request
return kwargs
'''
Form result2:
'''
class ResultFormView(RequestFormMixin, FormView):
""" View to show results of comparison between two files. """
template_name = 'tool/upload.html'
form_class = CompareFormTransporterCompany
success_url = reverse_lazy('tool:result')
By changing class ResultFormView(FormView): to class ResultFormView(RequestFormMixin, FormView):, it's working.
Sorry for this question, I'm still pretty new to Django and I didn't give all the informations needed.
I've been trying to set up a basic private messaging system in Django using the generic CreateView.
I am currently having trouble with the "Receiver"/"To" field in my form. I tried to make it so it was a drop down field with the options being followers of the logged-in user.
Currently, the field is populating with the correct usernames (in this case, "testuser1") but it is throwing an error saying this field needs to be populated with an instance of the User object.
ValueError: Cannot assign "'testuser1'": "Message.reciever" must be a "User" instance.
Is there a way to have the form pass in the object of the username that is selected?
Model:
class Message(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sender")
reciever = models.ForeignKey(User, on_delete=models.CASCADE, related_name="reciever")
subject = models.CharField(max_length=128, default="-")
content = models.TextField()
send_date = models.DateTimeField(default=timezone.now)
User Relationships Model:
class UserRelationships(models.Model):
user_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="following")
following_user_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="followers")
created = models.DateTimeField(auto_now_add=True)
UPDATED Form:
class MessageCreateForm(forms.ModelForm):
class Meta:
model = Message
fields = ['sender', 'reciever', 'subject', 'content']
widgets = {'sender': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
follower_objects = kwargs.pop('follower_objects')
super(MessageCreateForm, self).__init__(*args, **kwargs)
self.fields['reciever'] = RecieverModelChoiceField(queryset=User.objects.filter(username__in=follower_objects))
View:
class MessageCreateView(LoginRequiredMixin, CreateView):
model = Message
template_name = 'message/compose.html'
form_class = MessageCreateForm
def get_initial(self):
initial = super().get_initial()
initial['sender'] = self.request.user
return initial
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
user = self.request.user
followers = user.followers.values_list('user_id', flat=True)
follower_objects = []
kwargs['user'] = self.request.user
kwargs['follower_objects'] = follower_objects
for id in followers:
follower = User.objects.get(id=id)
follower_objects.append(follower)
return kwargs
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
You have to use forms.ModelChoiceField instead of forms.ChoiceField
ForeignKey (model) > ModelChoiceField (form) - Default widget: Select
ModelChoiceField has attribute queryset.
You can filter field reciever.queryset directly in MessageCreateForm.__init__ method.
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(MessageCreateForm, self).__init__(*args, **kwargs)
self.fields['reciever'].queryset = user.followers
UPDATE:
You can set a custom ModelChoiceField that will return any label you want (more info).
from django.forms import ModelChoiceField
class RecieverModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return obj.username
or
def __init__(self, *args, **kwargs):
....
self.fields['reciever'].label_from_instance = lambda obj: "%s" % obj.username
I have a model StaffProfile.while creating a form for Visiti want to get staff_user data(Based on current user) to that ChoiceField (to_meet).
models.py
class StaffProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name="user_profile")
staff_user = models.ManyToManyField(User, null=True, blank=True,
related_name="staff_user")
class Visit(models.Model):
name = models.CharField(max_length=200, name="name")
gender = models.CharField(choices=GENDER_CHOICE, max_length=1, name="gender")
mobile = models.CharField(max_length=18, default="", name="mobile")
to_meet = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
class VisitForm(forms.ModelForm):
to_meet = forms.ChoiceField(choices=[], required=False, label="Select Staff")
class Meta:
model = Visit
fields = ("__all__")
def __init__(self, *args, **kwargs):
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = StaffProfile.objects.filter(user=request.user).values_list("staff_user")
Initially override the __init__() method of your view
class VisitForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = [self.request.user]
to_meet = forms.ChoiceField(choices=[], required=False, label="Select Staff")
class Meta:
model = Visit
fields = "__all__" # small typo here
Then, in your view,
def foo_view(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = VisitForm(request.POST,request=request)
# check whether it's valid:
if form.is_valid():
# do somrthing
.....
You need to pass the request from view to form. For example:
def some_view(request):
form = VisitForm(request=request)
# rest of the code
and use it in the form:
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = StaffProfile.objects.filter(user=request.user).values_list("staff_user")
I'm trying to make inline forms with class based views, i followed the instrunctions from here. The only change i've made was to give self.request.user instead of self.object to instance:
models.py
class Client(models.Model):
user = models.OneToOneField(CustomUser)
translate = models.BooleanField(default=False)
class ClientData(models.Model):
client = models.ForeignKey(Client)
language = models.ForeignKey(Language)
forms.py
class ClientForm(ModelForm):
class Meta:
model = Client
fields = '__all__'
exclude = ['user', ]
class ClientDataForm(ModelForm):
class Meta:
model = ClientData
fields = '__all__'
exclude = ['client', ]
ClientFormSet = inlineformset_factory(Client, ClientData, form=ClientDataForm, extra=1)
views.py
class ClientView(LoginRequiredMixin, UpdateView):
model = Client
fields = '__all__'
success_url = reverse_lazy('core:index')
class ClientDataView(LoginRequiredMixin, UpdateView):
template_name = 'core/client_data.html'
model = ClientData
form_class = ClientDataForm
success_url = reverse_lazy('core:index')
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
def get_context_data(self, **kwargs):
context = super(ClientDataView, self).get_context_data(**kwargs)
if self.request.POST:
context['client_data'] = ClientFormSet(self.request.POST, instance=self.get_object())
else:
context['client_data'] = ClientFormSet(instance=self.get_object())
return context
def form_valid(self, form):
context = self.get_context_data()
client_data = context['client_data']
with transaction.atomic():
self.object = form.save()
if client_data.is_valid():
client_data.instance = self.object
return super(ClientDataView, self).form_valid(form)
Whenever i try to enter the page i get:
ValueError: Cannot query "asd#gmail.com": Must be "Client" instance.
[13/Dec/2017 15:48:36] "GET /client-data/ HTTP/1.1" 500 143759
for this line:
context['client_data'] = ClientFormSet(instance=self.get_object())
Your get_object is returning a ClientData instance.
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
However, as the error suggests, the instance should be a Client instance, for example:
def get_object(self, queryset=None):
profile = get_object_or_404(Client, user=self.request.user)
return profile
Or you can simply follow the one-to-one relation backwards:
def get_object(self, queryset=None):
return self.request.user.client