Django UpdateView, get the current object being edit id? - python

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

Pass kwarg into an inlineformset_factory?

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

How to pass data to the model field when saving the form? django form models save

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)

How to detailview pk in post method in DetailView? (Django)

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

Django CBV - set form class based on permissions?

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

Django CreateView didn't return an HttpResponse object

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)

Categories