including extra context value django rest framework - python

I am using django rest framework. I need to pass some extra context value in response but not getting extra_value in response.
class ResultRowView(generics.ListAPIView):
serializer_class = ResultRowSerializer
permission_classes = (AccountPermission, )
def get_serializer(self, *args, **kwargs):
context = {'extra_value': 5000}
return self.serializer_class(*args, context=context, **kwargs)
def get_queryset(self):
qs = ResultRow.objects.none()
pk = self.kwargs.get('pk', None)
try:
route = IncomingRoute.objects.get(account=self.request.user.account, pk=pk)
qs = route.app_module.rows.all()
except Exception, e:
print 'result_row_query: ', e
return qs
What is missing here ?

you can do this by overriding the list method like:
def list(self, request, *args, **kwargs):
response = super(ResultRowView, self).list(request, args, kwargs)
response.data[ 'extra_value' ] = 5000
return response

You will have to override the get_context_data method and then add context to it
def get_context_data(self, **kwargs):
context = super(PropertyListView, self).get_context_data(**kwargs)
context['some_key'] = some_value
return context

Related

get context data in get_queryset

I have BaseContext and Listview which is for Searching in multiple models, Search Class inherits from BaseContext. I set the current user to context and want to use it in my def get_queryset method, But it doesn't work. I think in Search CBV get_context_data execute after get_queryset that's why, self.user is None.
class BaseContext(ContextMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
request = self.request
if request.COOKIES.get('token') is not None:
...
user = Users.objects.filter(user_id=user_id).first()
context.update({'current_user': user})
context.update({'is_logged_in ': True})
else:
context.update({'is_logged_in ': False})
return context
class Search(BaseContext, ListView):
template_name = 'search.html'
context_object_name = "results"
paginate_by = 15
user = None
def get_queryset(self):
query = self.request.GET.get('search', None)
if query is not None and self.user is not None:
...
return queryset_chain
return faqModel.objects.none()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if 'is_logged_in' in context and context['is_logged_in']:
self.user = context['current_user']
else:
redirect("index")
return context
My question is how can I get context data in def get_queryset(self)?
for Listview get_quersyset() is called before get_contex_data() , hence getting context data is not possible in get_queryset()

How to get data from forms?

How can I get data from a form (ProductCreateForm)?
If I write form = self.get_form(), then I just get a form template, where some data is selected, and some are not (select especially).
If I write form = ProductCreateForm(request.POST), then I get an error saying that the request was not found. Perhaps this is due to the fact that I set the request in get_context_data() and work with them in the __init__ method in the forms.py.
I process the data in the clean method in the forms.py.
I have the following view
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
http_method_names = ['get', 'post']
def get_initial(self):
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
​
def get_context_data(self, *args, **kwargs):
ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
​
def get(self, request, *args, **kwargs):
self.object = None
if kwargs.get('slug'):
category = Category.objects.filter(slug=kwargs.get('slug')).first()
self.initial.update({'category': category})
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = ProductCreateForm(request.POST) #What here?
special_form = SpeciallyPriceForm(self.request.POST)
​
if form.is_valid() and special_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
forms
class ProductCreateForm(forms.ModelForm):
#....
​
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('initial').get('request')
super(ProductCreateForm, self).__init__(*args, **kwargs)
#...
user = self.request.user
provider = Provider.objects.filter(user=user.id).last()
self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all())
#...
def clean(self):
cleaned_data = super(ProductCreateForm, self).clean()
cd_category = cleaned_data.get('category')
#...
​
​
class SpeciallyPriceForm(forms.ModelForm):
class Meta:
model = SpeciallyPrice
fields = ['adittional_specially_price', 'adittional_specially_number']
1.try pass request in that way
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
then in forms.py
def __init__(self):
kwargs.pop('initial').get('request')
Are you sure that is working at all? On init in your forms I don't see super() call so you should get an error?
Do you have problem only with category field the rest data you get properly?
Where do you pass it kwargs.pop('request') ??
You can print and check what is in self.request.POST

Django: object has no attribute 'object'

I have to implement several forms, therefore I need the combination of SingleObjectMixin, TemplateView. I always receive 'AssignAttendee' object has no attribute 'object'. Do you see why I get that error?
class AssignAttendee(SuccessMessageMixin, SingleObjectMixin, TemplateView):
template_name = 'attendees/front/assign_attendee.html'
success_message = _("Attendee has been successfully updated.")
def get_object(self):
return get_object_or_404(
Attendee,
ticket_reference=self.kwargs['ticket_reference'],
ticket_code=self.kwargs['ticket_code'],
)
#cached_property
def attendee_form(self):
return AssignAttendeeForm(
prefix='attendee',
data=self.request.POST or None,
# instance=self.attendee_contact,
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context = {
'attendee_form': self.attendee_form,
}
The problem was that it was missing:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, *args, **kwargs)

HttpResponseRedirect not working in django

HttpResponseRedirect not working it shows error as 'context must be dict rather than response'
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type == 'page':
try:
context['page_obj'] = obj
return context
except:
pass
else:
pass
print(obj.url_name)
return HttpResponseRedirect(str(obj.url_name))
get_context_data() is the method for return context, so it must return context object. If you want to redirect, do it in get().
like below
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
return HttpResponseRedirect(str(obj.url_name))
else:
return super().get(*args, **kwargs)
# if python2
# return super(FooterLinksView, self).get(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type == 'page':
try:
context['page_obj'] = obj
return context
except:
pass
return context
or you can just use extra_context in TemplateView.
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
try:
self.extra_context = {
'page_obj': obj
}
except:
pass
return HttpResponseRedirect(str(obj.url_name))
else:
return super().get(*args, **kwargs)
# if python2
# return super(FooterLinksView, self).get(*args, **kwargs)
You must always return a dict from your get_context_data function. If you want to redirect, you should override dispatch too:
class FooterLinksView(TemplateView):
...
def dispatch(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
return HttpResponseRedirect(str(obj.url_name))
return super(FooterLinksView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
context['page_obj'] = obj
return context
The code in your get_context_data is trying to retrieve a single object and passing it to the context dictionary. This functionality is already built-in the DetailView and seems to be a better fit here than the TemplateView.
from django.views.generic import DetailView
class FooterLinksView(DetailView):
model = FooterLink
template_name = 'pages/footerlinks.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if self.object.link_type == 'page':
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
return HttpResponseRedirect(str(obj.url_name))
Now the only thing we need to add is how the FooterLink object is retrieved in the get_object method. If your link_url field of FooterLink is the primary key we can simply add pk_url_kwarg = 'link_url' in the top of the class. Otherwise you should use the slug_field and slug_url_kwarg.
class FooterLinksView(DetailView):
model = FooterLink
pk = 'link_url' # if link_url is the primary key
slug_field = 'link_url' # if link_url is not the primary key
slug_url_kwarg = 'string' # if link_url is not the primary key
template_name = 'pages/footerlinks.html'
...
Note: You should now use the object variable inside your template (instead of obj) or override yet another option: context_object_name.
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, args, *kwargs):
context = self.get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = get_object_or_404(FooterLink, link_url=string_name)
if obj.link_type == 'page':
context['page_obj'] = obj
return render(request, self.template_name, context)
else:
a = obj.url_name
return HttpResponseRedirect(a)

Django REST Framework : update() based on query string parameter

Is it possible to modify a ViewSet's update() function to update based on a query string parameter instead of a URL resource name or the request body?
For example, I want trigger something like this:
payload = {'field' : '2'}
r = requests.put("http://127.0.0.1:9876/job-defs?job-def-id=2", data=payload)
and have this update my field when job-def-id = 2.
What I have so far is this:
class JobDefinitionsViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
serializer_class = JobDefinitionsSerializer
def update(self, request, pk=None):
job_def_id = self.request.query_params.get('job-def-id', None)
super(JobDefinitionsViewSet, self).update(self, request, pk=job_def_id)
...
# other unrelated code
...
I'm not too sure how to continue.
I want to reuse as much as the update() function from mixins.UpdateModelMixin as possible.
Any help is appreciated.
Assuming you want to use the same url for listing and for retrieving the details of the entity, discriminating on the presence of the url parameter job-def-id, here is a crazy idea:
class JobDefinitionsAllInOneView(mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = JobDefinitions.objects.all()
serializer_class = JobDefinitionsSerializer
def get_object(self):
job_def_id = self.request.query_params.get('job-def-id', None)
if job_def_id is not None:
self.kwargs['pk'] = job_def_id
return super(JobDefinitionsAllInOneView, self).get_object()
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
job_def_id = self.request.query_params.get('job-def-id', None)
if job_def_id is not None:
# return the details
return self.retrieve(request, *args, **kwargs)
else:
# return a list
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(self, request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(self, request, *args, **kwargs)
I haven't tried it yet. I had a look at the source code here for get_object and here for the mixins

Categories

Resources