Why would one use a Base view in Django when this
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
can be written as
def get(request):
return HttpResponse('Hello, World!')
What is the advantage of the Base view vs the function view?
All sorts of reasons.
You want to make use of a specialized view, like the TemplateView mentioned by #pythonista that makes it a lot easier for you to write your view. e.g.,
class MyTemplateView(TemplateView):
template_name = 'template.html'
You want to have some isolation when you have similar behavior. For example, you want a class-based View to handle both the form rendering and the form post:
class MyFormView(TemplateView):
template_name = 'form.html'
def get(self, request, *args, **kwargs):
return super(MyFormView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs:
value1 = request.POST.get('value1')
value2 = request.POST.get('value2')
# handle the post values
return super(MyFormView, self).get(request, *args, **kwargs)
You have REST endpoint and you’d like to isolate all of the code for GET/POST/PUT/DELETE in a single class-based view.
class RestEndpoint(View):
def __init__(self):
super(RestEndpoint, self).__init__()
self.model = MyModel
def get(request, n_id, *args, **kwargs):
x = self.model.objects.get(id=n_id)
return JsonResponse(x.to_json())
def put(self, request, *args, **kwargs):
data = json.loads(request.body)
x = self.model(**data)
x.save()
return JsonResponse(x.to_json())
def post(self, request, n_id, *args, **kwargs):
data = json.loads(request.body)
x = self.model.objects.get(id=n_id)
for key, value in data.items():
setattr(x, key, value)
x.save()
return JsonResponse(x.to_json())
def delete(self, request, n_id, *args, **kwargs):
self.model.objects.filter(id=n_id).delete()
return JsonResponse({})
You just prefer using classes instead of functions, e.g., so that you can create your own fun base views and reuse code with inheritance.
Related
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)
I work on the API in the Django REST Framework. And now there is such a problem: there is a ModelViewSet and in its functions the same request to the database, the same check in the if block. Is it possible to somehow move this matter into a separate function and how to do it?
class LinkViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = LinkSerializer
queryset = Link.objects.all()
def retrieve(self, request, *args, **kwargs):
instance = Link.objects.filter(Q(user_id=self.request.user.id) & Q(id=kwargs["pk"])).first()
if not instance:
return Response(data="Not found", status=status.HTTP_404_NOT_FOUND)
return super().retrieve(request, *args, **kwargs)
def partial_update(self, request, *args, **kwargs):
instance = Link.objects.filter(Q(user_id=self.request.user.id) & Q(id=kwargs["pk"])).first()
if not instance:
return Response(data="Not found", status=status.HTTP_404_NOT_FOUND)
return super().partial_update(request, *args, **kwargs)
If I understand the code correctly, the intention is to limit queryset to allow access only to links owned by currently logged in user. For that, you can just override get_queryset method and that is it. DRF will take care of getting object from the queryset by id and throwing 404 if the object is not found.
class LinkViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = LinkSerializer
def get_queryset(self):
return Link.objects.filter(user_id=self.request.user.id)
You could do some of the implementation in a private method
def _link_objects_filter(self, pk):
return Link.objects.filter(Q(user_id=self.request.user.id)
& Q(pk)).first()
Or, taking it a step further, have a common implementation that uses getattr to decide which base implementation to use.
class LinkViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = LinkSerializer
queryset = Link.objects.all()
def _retrieve_op(self, method, request, *args, **kwargs):
instance = self._link_objects_filter(kwargs["pk"])
if not instance:
return Response(data="Not found", status=status.HTTP_404_NOT_FOUND)
return getattr(super(), method)(request, *args, **kwargs)
def retrieve(self, request, *args, **kwargs):
return self._retrieve_op("retrieve", request, *args, **kw)
def partial_update(self, request, *args, **kwargs):
return self._retrieve_op("partial_update", request, *args, **kw)
def _link_objects_filter(self, pk):
return Link.objects.filter(Q(user_id=self.request.user.id)
& Q(pk)).first()
That could be further reduced with partial methods
import functools
class LinkViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = LinkSerializer
queryset = Link.objects.all()
def _retrieve_op(self, request, method, *args, **kwargs):
instance = self._link_objects_filter(kwargs["pk"])
if not instance:
return Response(data="Not found", status=status.HTTP_404_NOT_FOUND)
return getattr(super(), method)(request, *args, **kwargs)
retrieve = functools.partialmethod(_retrieve_op, "retrieve")
partial_update = functools.partialmethod(_retrieve_op, "partial_update")
def _link_objects_filter(self, pk):
return Link.objects.filter(Q(user_id=self.request.user.id) & Q(pk)).first()
I'm not sure whether django meta programming will mess this up.
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)
my view is like this
class RecordView(View):
record_form = RecordForm
record_files = {}
templare = 'acquisition.html'
def get(self, request, *args, **kwargs):
fil = urllib.urlopen('/home/student/wwww.jpg')
self.record_files = {'small_cover': SimpleUploadedFile('hehe.jpg', fil.read())}
rr_form = self.record_form()
return render(request, self.template_name, {'rr_form': rr_form,
})
def post(self, request, *args, **kwargs):
record = RecordForm(request.POST, self.record_files)
record.save()
HttpResponseRedirect('/')
Here i have populated self.record_files in get method.. but after i post data i see self.record_files as empty dictionary. I get confused here. What can i do to do so.
The state of your view instance is not maintained between a get and a post, so setting record_files on the instance will not keep it for the next request. You would need to put that logic in the dispatch method, or store information in the user's session.
class RecordView(View):
record_form = RecordForm
record_files = {}
templare = 'acquisition.html'
# dispatch is called before deciding whether to use get() or post()
# so any instance-level properties that require the request can go here.
# This could even go in __init__().
def dispatch(self, request, *args, **kwargs):
fil = urllib.urlopen('/home/student/wwww.jpg')
self.record_files = {'small_cover': SimpleUploadedFile('hehe.jpg', fil.read())}
return super(RecordView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
rr_form = self.record_form()
return render(request, self.template_name, {'rr_form': rr_form,
})
# self.record_files will be available in a get, or a post (or any valid
# method for that matter).
def post(self, request, *args, **kwargs):
record = RecordForm(request.POST, self.record_files)
record.save()
return HttpResponseRedirect('/')
That is exactly how it suppose to work. Whenever you have a GET request, it will call method get, and if it is a POST request, naturally it will call post method, but not the get method. So here is how you can solve your problem:
from django.views.generic import TemplateView
class RecordView(TemplateView):
record_form = RecordForm
record_files = {}
template_name = 'acquisition.html'
def get_context_data(self, **context):
fil = urllib.urlopen('/home/student/wwww.jpg')
self.record_files = {
'small_cover': SimpleUploadedFile('hehe.jpg', fil.read())
}
context.update({
'record_files': self.record_files,
'rr_form': self.record_form()
})
fil.close()
return super(RecordView, self).get_context_data(**context)
def post(self, request, *args, **kwargs):
context = self.get_context_data()
record_form = self.record_form(request.POST, self.record_files)
if record_form.is_valid():
record_form.save()
## or do a redirect instead, like you had before:
# return HttpResponseRedirect('/')
context['rr_form'] = record_form
return self.render_to_response(context)
This is my URL
url(r'^users/(?P<pk>\d+)/testy/$', views.MyModelUpdate.as_view(model=models.User,
form_class=forms.UserForm, myVariable='testing'), name='my_update'),
This is my class view
class MyModelUpdate(UpdateView):
def get(self, request, *args, **kwargs):
How can i get myVariable here
This should do the trick:
def get(self, request, *args, **kwargs):
pk=kwargs['pk']
myVariable=self.kwargs['myVariable']
Edit
How about:
def get(self, request, myVariable, *args, **kwargs):