This is my code:
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django import http
from django.http import HttpResponse
def main(request, template_name='index.html'):
HttpResponse.set_cookie('logged_in_status', 'zjm1126')
context ={
'a':a,
'cookie':HttpResponse.get_cookie('logged_in_status'),
}
return render_to_response(template_name, context)
#return http.HttpResponsePermanentRedirect(template_name)
It raises this exception:
unbound method set_cookie() must be called with HttpResponse instance as first argument (got str instance instead)
What can I do?
You can't just start calling methods on the HttpResponse class, you have to instantiate it e.g. response = HttpResponse("Hello World"), call the cookie method, and then return it from your view.
response = render_to_response(template_name, context)
response.set_cookie('logged_in_status', 'never_use_this_ever')
return response
# remember my other answer:
# it's a terrrible idea to set logged in status on a cookie.
To get the cookie:
request.COOKIES.get('logged_in_status')
# remember, this is a terrible idea.
In case you want the raw cookie string (tested with Django 4.1)
request.META.get('HTTP_COOKIE')
Related
I'm building a system where I store a Member model on a Django server, one of the attributes of Member is score which is what I want to change using API calls. My question is what would be the best way to do this? I looked into the Django REST framework but it seems a bit overkill for what I'm trying to do. I've been trying to pass the necessary information through the url using regular expressions but I'm unsure if it will work. Outline of what I need is below
iOS/Android app makes request sending pk and score to add to total
server updates appropriate model instance and returns True/False to app depending if save was successful
You can achieve this by this quite dirty solution:
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:member_id>/<int:score_to_add>/', views.update_score, name='update_score'),
]
views.py
from django.http import HttpResponse
from .models import Member
def update_score(request, member_id, score_to_add):
member = Member.objects.get(pk=member_id)
member.score += score_to_add
try:
member.save
return HttpResponse("True")
except:
return HttpResponse("False")
Also you can respond with Json. Here is alternative views:
Alternative views.py
from django.http import JsonResponse
from .models import Member
def update_score(request, member_id, score_to_add):
member = Member.objects.get(pk=member_id)
member.score += score_to_add
try:
member.save
return JsonResponse({'status': True})
except:
return JsonResponse({'status': False})
But i think Django Rest Framework is a better way to do this.
You can create a view to return JsonResponse. Take example of polls app in django and convert a post view to return a JSON response.
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.http import JsonResponse
from .models import Choice, Question
# Need to disable csrf here
#csrf_exempt
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
# If you want Json requests Or you can use
# received_json_data=request.POST if you are using normal form data request.
received_json_data=json.loads(request.body)
try:
selected_choice = question.choice_set.get(pk=received_json_data['choice'])
except (KeyError, Choice.DoesNotExist):
# If failed
return JsonResponse({'result': False})
else:
selected_choice.votes += 1
selected_choice.save()
return JsonResponse({'result': True})
Although It works but I would still recommend using DRF because what you are doing needs proper REST API and DRF eases a lot of pain points.
I use Django Rest Framework with rest_auth (/login, /logout/, /register...)
I have a Middleware, normally triggered by user_logged_in or user_logged_out signals.
In my Middleware, I want to use Response object from Rest framework.
My middleware.py
from django.contrib.sessions.models import Session
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from rest_framework.response import Response
from rest_framework import status
class OneSessionPerUserMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated:
if request.user.session_key != Session.objects.filter(session_key__in = request.user.session_key):
logout(request)
return Response(request)
return self.get_response(request)
I suppose that I pass my condition, but I get this error :
The response content must be rendered before it can be accessed
How to use correctly the API Response object in a middleware ?
And I don't understand really what is : self.get_response = get_response ?
return Response(request) is not something django can handle. Ps you are passing request object to Response what does that mean?
Actually Request and Response classes from rest framework are not compatible with django. rest framework wraps WSGIRequest (django's builtin) with Request object in APIView and after getting Response object from view, it creates HttpResponse object by unwrapping it. So Response object can only be used in rest framework views. You can use JsonResponse from django.http in middleware like this
from django.http import JsonResponse
if request.user.is_authenticated:
if request.user.session_key != Session.objects.filter(session_key__in = request.user.session_key):
logout(request)
return JsonResponse({'logout': True}) # or whatever data you want to return
return self.get_response(request)
First of all: if you are using something other than rest_framework.authentication.SessionAuthentication as an authentication_class, then request.user is set outside of middlewares (somewhere during View.dispatch)
If you are sure that request.user is always corresponding to request.user inside rest_framework views and just want to return a response:
A. Look at the APIView.finalize_response: it's relatively "complex" because it can use different renderers (depending on accept-content request header), it may change headers. If you can access instance of your view in the middleware, then you can call view.finalize_response(request, response), if you don't have it then you can try doing rest_framework.views.APIView().finalize_response(...)
B. You can use django.http.HttpResponse: manually generate string for body, and specify appropriate content_type. And django.http.JsonResponse may be handy too.
C. I assumed that instead of return Response(request) you really are doing something else (like Response(data=...)). If you just need to return results from view, then remove return Response(request), so that return self.get_response(request) kicks in. But you are making a logout, so maybe you should return some instance of django.http.HttpResponseRedirect
I am trying to use REST API in django for retrieve some data in json format.
When i hit this url:
http://192.168.2.87:8000/locker/123/
It gives me output like this (from Database)
{"id": 1, "locker_id": 123, "locker_user_name": "taimur"}
But if i want to get the output by passing the parameters like this
http://192.168.2.87:8000/locker/?locker_id=123&locker_user_name=taimur&id=1
views.py
from postman, How can i do this??
from django.shortcuts import render, HttpResponse, get_object_or_404
from django.http import JsonResponse
from .models import Locker
from .serializers import LockerSerializer
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
def locker_data_response(request, locker_id):
if request.method == 'GET':
locker_information = get_object_or_404(Locker, locker_id = locker_id)
print(locker_information)
locker_information_serialize = LockerSerializer(locker_information)
print(locker_information_serialize)
return JsonResponse(locker_information_serialize.data)
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
re_path('(?P<locker_id>[0-9]+)/$', views.locker_data_response, name='locker_data_response'),
]
You get them from the request object:
def locker_data_response(request):
if request.method == 'GET':
locker_id = request.data.get('locker_id') # this will return None if not found
locker_user_name = request.data.get('locker_user_name')
locker_information = get_object_or_404(Locker, locker_id=locker_id)
print(locker_information)
locker_information_serialize = LockerSerializer(locker_information)
print(locker_information_serialize)
return JsonResponse(locker_information_serialize.data)
And the url will change to:
locker/$
[EDIT: Sorry, if you are using drf you should use data rather than GET]
[EDIT 2: If you want to use it like this, you will also need to change the url and signature of the view]
[EDIT 3: Added the code in the correct place in view]
If your url is something like domain/search/?q=haha, Then you would use request.GET.get('q', '').
q is the parameter you want, And '' is the default value if q isn't found.
If you are instead just configuring your URLconf, Then your captures from the regex are passed to the function as arguments (or named arguments).
Such as:
(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),
Then in your views.py you would have
def profile_page(request, username):
# Rest of the method
I am learning Django's class-based views.
I don't understand what's the instance created from class Views
For example:
from django.http import HttpResponse
from django.views import View
# views.py
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')
# urls.py
from django.conf.urls import url
from myapp.views import MyView
urlpatterns = [
url(r'^about/$', MyView.as_view()),
]
What's the instance of class 'MyView' during this request-and-respond process?
Although your question is not very clear, I think that I get what you are asking:
Take a look at the source code of url() method:
def url(regex, view, kwargs=None, name=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return RegexURLResolver(
regex, urlconf_module, kwargs,
app_name=app_name, namespace=namespace
)
...
And a look at the as_view() method documentation:
Returns a callable view that takes a request and returns a response:
response = MyView.as_view()(request)
The returned view has view_class and view_initkwargs attributes.
When the view is called during the request/response cycle, the HttpRequest is assigned to the view’s request attribute.
Therefore because you are passing in the url method the MyView.as_view() argument you are giving the instruction to instantiate the MyView class when a request object gets passed to the url() method.
I am using Django 1.11 and django-settings-export, but it is not working for this view:
from django.shortcuts import render_to_response
def foo(request):
return render_to_response('foo.html', {})
Fixed changing render_to_response to render.
from django.shortcuts import render
def foo(request):
return render(request, 'foo.html', {})
Checking Django documentation, render_to_response is not recommended and will be deprecated.
This function preceded the introduction of render() and works similarly except that it doesn’t make the request available in the response. It’s not recommended and is likely to be deprecated in the future.