I am trying to get the current record being edited's id, but am failing thus far. my view is as per the below:
views.py
class EditSite(UpdateView):
model = SiteData
form_class = SiteForm
template_name = "sites/site_form.html"
#method_decorator(user_passes_test(lambda u: u.has_perm('config.edit_subnet')))
def dispatch(self, *args, **kwargs):
self.site_id = self.object.pk
return super(EditSite, self).dispatch(*args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy("sites:site_overview", args=(self.site_id,))
def get_form_kwargs(self, *args, **kwargs):
kwargs = super().get_form_kwargs()
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['SiteID']=self.site_id
context['SiteName']=self.location
context['FormType']='Edit'
return context
and the error:
File "/itapp/itapp/sites/views.py" in dispatch
890. self.site_id = self.object.pk
Exception Type: AttributeError at /sites/site/edit/7
Exception Value: 'EditSite' object has no attribute 'object'
ive tried:
self.object.pk
object.pk
self.pk
The view's object attribute is set during get/post by BaseUpdateView:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).post(request, *args, **kwargs)
So it is not yet available in the dispatch method.
But it will be available in the get_success_url and get_context_data methods as those happen after get/post. So you could do:
from django.contrib.auth.mixins import PermissionRequiredMixin
class EditSite(PermissionRequiredMixin, UpdateView):
model = SiteData
form_class = SiteForm
template_name = "sites/site_form.html"
permission_required = 'config.edit_subnet'
def get_success_url(self, **kwargs):
return reverse_lazy("sites:site_overview", args=(self.object.site_id,))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['SiteID']=self.object.site_id
context['SiteName']=self.location # <--- where does self.location come from? self.object.location perhaps?
context['FormType']='Edit'
return context
Related
I am trying to pass the request object into my inlineformset_factory and am struggling to accomplish this.
In forms.py I have the following:
class SummativeScoreForm(forms.ModelForm):
"""
Form definition for SummativeScore Form
"""
subdomain_proficiency_level = forms.ModelChoiceField(
empty_label="Undecided",
queryset=SubdomainProficiencyLevel.objects.none(),
widget=forms.RadioSelect,
required=False,
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(SummativeScoreForm, self).__init__(*args, **kwargs)
if self.instance:
if self.request.user == self.instance.summative.employee:
self.fields["subdomain_proficiency_level"].disabled = True
self.fields[
"subdomain_proficiency_level"
].queryset = SubdomainProficiencyLevel.objects.filter(
subdomain=self.instance.subdomain
)
self.fields[
"subdomain_proficiency_level"
].label = f"""
{self.instance.subdomain.character_code}:
{self.instance.subdomain.short_description}
"""
class Meta:
model = SummativeScore
fields = "__all__"
widgets = {
"subdomain_proficiency_level": forms.RadioSelect(
attrs={"class": "list-unstyled"}
),
}
SummativeScoreInlineFormset = inlineformset_factory(
Summative,
SummativeScore,
fields=("subdomain_proficiency_level",),
can_delete=False,
extra=0,
form=SummativeScoreForm,
)
I'm using a FormView CBV to show this inline_formset
class SummativeScoreFormView(
LoginRequiredMixin,
UserIsObserverOrObserveeMixin,
SingleObjectMixin,
FormView,
):
model = Summative
template_name = "commonground/summative_score_form.html"
pk_url_kwarg = "summative_id"
def get(self, request, *args, **kwargs):
summative_id = kwargs.pop("summative_id")
self.object = self.get_object(
queryset=Summative.objects.filter(id=summative_id)
)
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
summative_id = kwargs.pop("summative_id")
self.object = self.get_object(
queryset=Summative.objects.filter(id=summative_id)
)
return super().get(request, *args, **kwargs)
def get_form(self, form_class=None):
return SummativeScoreInlineFormset(
**self.get_form_kwargs(), instance=self.object
)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["request"] = self.request
return kwargs
def form_valid(self, form):
form.save()
messages.add_message(messages.SUCCESS, "Changes were saved!")
HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form):
print("invalid form")
return super().form_invalid(form)
def get_success_url(self):
user_id = self.kwargs["user_id"]
summative_id = self.kwargs["summative_id"]
return reverse(
"commonground:summative_detail",
kwargs={
"user_id": user_id,
"summative_id": summative_id,
},
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
summative = get_object_or_404(
Summative, pk=self.kwargs["summative_id"]
)
context["summative"] = summative
return context
I keep getting this error:
__init__() got an unexpected keyword argument 'request'
I'm not sure how best to resolve this - any ideas? Is there a clear way to pass the request to the inlineformset_factory?
You are passing the request to the formset and not to the forms in the formset, hence you get the error. For passing custom parameters to the formsets forms [Django docs] you need to pass a form_kwargs parameter to the formset:
class SummativeScoreFormView(
LoginRequiredMixin,
UserIsObserverOrObserveeMixin,
SingleObjectMixin,
FormView,
):
...
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['form_kwargs'] = {'request': self.request}
return kwargs
get the form and process it in post. It is necessary to save the unique uuid of the record to the model, I do it like this: formOne.save(related_uuid=related_uuid)
but doesn't work, the error is - save() got an unexpected keyword argument 'related_uuid'
models
class Orders(models.Model):
device = models.CharField(max_length=150)
uuid = models.CharField(max_length=22, blank=True)
views
class OrderAddView(TemplateView):
template_name = 'orders/order_add.html'
def get(self, request, *args, **kwargs):
context = super().get_context_data(**kwargs)
... some work code
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
formOne = SimpleOrderAddForm(self.request.POST, prefix='one_form')
if formOne.is_valid():
related_uuid = shortuuid.uuid()
formOne.save(related_uuid=related_uuid)
return HttpResponseRedirect('orders_home')
else:
print('NotValid')
return self.form_invalid(formOne, **kwargs)
def form_invalid(self, formOne,, **kwargs):
context = self.get_context_data()
... some work code
return self.render_to_response(context)
assuming that "shortuuid.uuid()" return correct uuid; try
def post(self, request, *args, **kwargs):
formOne = SimpleOrderAddForm(self.request.POST, prefix='one_form')
if formOne.is_valid():
a=formOne.save(commit=False)
a.related_uuid=shortuuid.uuid()
a.save()
return HttpResponseRedirect('orders_home')
else:
print('NotValid')
return self.form_invalid(formOne, **kwargs)
In my detailView I have 2 methods get_context_data and post. In get_context_data I can get the detailView pk with self.object.pk but how can I get it in the post method?
[ updated ]
here is the view
class Class_detailView(LoginRequiredMixin, DetailView):
login_url = '/'
model = Class
template_name = "attendance/content/teacher/class_detail.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['attendance_form'] = AttendanceForm(current_class_pk=self.object.pk) # pass data to form via kwargs
return context
def post(self, request, *args, **kwargs):
if request.method == "POST":
attendance_form = AttendanceForm(request.POST)
if attendance_form.is_valid():
attendance_form.instance.teacher = self.request.user
attendance_form.save()
return redirect('class-detail', pk=self.kwargs.get('pk'))
form
class AttendanceForm(forms.ModelForm):
class Meta:
model = Attendance
fields = ['student',]
def __init__(self, *args, **kwargs):
current_class_pk = kwargs.pop('current_class_pk')
super(AttendanceForm, self).__init__(*args, **kwargs)
current_student = Class.objects.get(id=current_class_pk)
self.fields['student'].queryset = current_student.student
I want to get the pk and pass it to the form when the post request is called.
How can I do it?
did you try this:
def post(self, request, *args, **kwargs):
if request.method == "POST":
attendance_form = AttendanceForm(request.POST, current_class_pk=self.kwargs.get('pk'))
if attendance_form.is_valid():
attendance_form.instance.teacher = self.request.user
attendance_form.save()
return redirect('class-detail', pk=self.kwargs.get('pk'))
I have created two forms in forms.py one form has less fields than the other.
what I would like to now do is get the current users permissions and set the form class of the CBV based on those perms.
below is my current view:
class EditCircuit(UpdateView):
model = Circuits
# if user_passes_test(lambda u: u.has_perm('config.edit_circuit')))
form_class = CircuitForm
# else
# form_class = CircuitFormRestricted
template_name = "sites/circuit_form.html"
#method_decorator(user_passes_test(lambda u: u.has_perm('config.edit_circuit')))
def dispatch(self, *args, **kwargs):
self.site_id = self.kwargs['site_id']
self.site = get_object_or_404(SiteData, pk=self.site_id)
return super(EditCircuit, self).dispatch(*args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy("sites:site_detail_circuits", args=(self.site_id,))
def form_valid(self, form):
form.instance.site_data = self.object.site_data
return super(EditCircuit, self).form_valid(form)
def get_form_kwargs(self, *args, **kwargs):
kwargs = super().get_form_kwargs()
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['SiteID']=self.site_id
context['SiteName']=self.site.location
context['FormType']='Edit'
context['active_circuits']='class="active"'
return context
You can override the get_form_class method.
def get_form_class(self):
if self.request.user.has_perm('config.edit_circuit'):
return CircuitForm
return CircuitFormRestricted
Also, it looks as though you don't need the get_form_kwargs definition, as it's not doing anything at the moment.
you can create your own mixin like this
class AuthorOnlyMixin(object):
def has_permissions(self):
return self.get_object().created_by == self.request.user
then use it like this
class EditViewClass(AuthorOnlyMixin, EditView):
def get_form_class(self):
if self.has_permissions():
return FormWithPermission
else:
return FormWithoutPermission
Can't figure out why CreateView doesn't return HttpResponse. For now, I use this view just for posting (no GET). I thought that set self.success_url should be enough (as you can see in def post).
class TripCreationView(CreateView):
form_class = TripCreationForm
template_name = 'frontend/homepage.html'
def post(self, request, *args, **kwargs):
self.success_url = request.POST.get('success_url') or reverse('frontend:homepage')
super(TripCreationView, self).post(self, request, *args, **kwargs)
#
# def form_valid(self, form):
# trip = form.save(self.request)
# return HttpResponseRedirect(self.success_url)
def get_form_kwargs(self):
kwargs = super(TripCreationView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Do you know what to do?
You forgot a return statement.
def post(self, request, *args, **kwargs):
self.success_url = request.POST.get('success_url') or reverse('frontend:homepage')
return super(TripCreationView, self).post(self, request, *args, **kwargs)