How to get request host in django? - python

How to get request host in django ?
how will I get host URL/name from request
class StoreLocations(APIView):
"""
GET : For fetching store locations
Returns : Store Locations
---------------
json
"""
permission_classes = []
http_method_names = ["get"]
def get(self, request, format=None):
"""
Want to check from where request is coming from and allow requests coming from specific urls only
"""

Use HttpRequest.get_host(...)
class StoreLocations(APIView):
def get(self, request, *args, **kwargs):
host = request.get_host()

You can use the below code snippet to see which host is used.
print(request.environ.get("HTTP_ORIGIN"))
To see the additional details present in request.
print(request.__dict__)

django request have META dictionary:https://docs.djangoproject.com/en/4.0/ref/request-response/#django.http.HttpRequest.META
I think you search for:
request.META['REMOTE_ADDR'] # e.g. '1.1.1.1'
request.META['REMOTE_HOST'] # e.g. '1.1.1.1'
request.META['HTTP_REFERER'] # this show url from where was made request

Related

Save query string data using rest framework in Django

I need to save to a database the query string data coming from a GET request using Django Rest framework.
Something like this:
URL: "http://127.0.0.1:8000/snippets/snippets/?longitude=123123&latitude=456456"
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
#code here for saving the query string data to database, in this case save:
#{
#"longitude":123123,
#"latitude":456456
#}
It's just like saving the params data like it were a POST request.
I need to save to a database the query string data coming from a GET request using Django Rest framework.
This is against the specifications of the HTTP protocol. Indeed, a GET request should only be used to retrieve data, not update data. For that a POST, PUT, PATCH or DELETE request should be used. The querystring is normally used to filter, not to store data.
If you really want to do this, you can override the .get(…) handler and
# Warning: against the HTTP protocol specifications!
class SnippetCreateView(generics.CreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
# {
# "longitude":123123,
# "latitude":456456
# }
def get(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
But this is really not a good idea.

Can't send GET request to Django via Postman

I perform request http://167.71.57.114/api/users/list-exercises
And receive error
User matching query does not exist.
How can I fix the error?
Found out that reason of the error is that request didn't have any data
But you can see that I am sendig the "user_id"
My code
class WorkoutUserProgramListViewAPI(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = WorkoutUserProgramListSerializer
def get(self, request):
response = {}
user = request.data.get("user_id") # user is None
user = User.objects.get(pk=user) # Error User matching query does not exist.
Like #Klaus D said in the comments, you would rather put a user-id as a parameter. If you're sending user_id=29, I would add that as a parameter, which should change the URL to be something like
http://167.71.57.114/api/users/list-exercises?user_id=29
That error occurs when the objects.get method does not find any result.
If you use filter and verify that the result is not None you avoid that error in the case that the id passed by parameter does not belong to any user.
class WorkoutUserProgramListViewAPI(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = WorkoutUserProgramListSerializer
def get(self, request):
response = {}
user_id = request.data.get("user_id")
user = User.objects.filter(pk=user_id).first()
if user is not None:
# code
else:
# code
Listen what Klaus D. tells you, too.

Set cookie in GraphQL mutation

I need to update a cookie in GraphQL mutation using graphene and Django.
My first idea was to add cookie to context (which is request) and then set it in middleware.
I have a very simple mutation that looks like that:
class SetWantedCookieMutation(graphene.Mutation):
class Arguments:
wanted_cookie = graphene.String(required=True)
ok = graphene.Boolean(required=True)
def mutate(self, info, wanted_cookie):
# set cookie here
info.context.wanted_cookie = wanted_cookie
return SetWantedCookieMutation(ok=True)
And Django Middleware is that:
class CookieMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if (hasattr(request, 'wanted_cookie')):
response.set_cookie('wanted_cookie', request.wanted_cookie)
return response
But I cannot get wanted_cookie in my CookieMiddleware.
Any ideas how to set cookie in mutation/moddlewere?
Or what are other ways to set cookie through graphene mutation?
One way to do this is to check the operation name in the json of the request:
class CookieMiddleware(MiddlewareMixin):
def generate_cookie(self, user):
# Generate a cookie (probably with the user)
def request_has_cookie_mutation(self, request):
# Returns true if the request's operation is SetWantedCookieMutation
if len(request.body) != 0 and 'operationName' in json.loads(request.body):
return json.loads(request.body)['operationName'] == 'SetWantedCookieMutation'
return False
def process_response(self, request, response):
if (self.request_has_cookie_mutation(request)):
new_cookie = self.generate_cookie(request.user)
response.set_cookie('wanted_cookie', new_cookie)
return response
Note that it looks like you're using a version of Django pre-1.10 and should consider upgrading.

How to get request params in Django admin custom column?

I need to keep information about filtering and searching in Django admin change page.
So when user filters by "?away_team__id__exact=267821", I need to append this query to change page url.
Let's say we filtered objects by query above. This is the url of change list:
http://127.0.0.1:8000/matches/match/?away_team__id__exact=267821
I want to make change column which redirects user to change page of the current object and appends query to the url so instead:
http://127.0.0.1:8000/matches/match/2009/change/
The url will be:
http://127.0.0.1:8000/matches/match/2009/change/?away_team__id__exact=267821
The problem is that I couldn't access request in the custom column method. I tried to do it using template language but without success, I get:
http://127.0.0.1:8000/matches/match/1996/change/?{{%20request.GET.urlencode%20}}
This is the method:
def change(self,obj):
return mark_safe(f"""<a class="changelink" href="{reverse("admin:matches_match_change",args=(obj.pk,))}"""+"?{{ request.GET.urlencode }}\""+"><span class='icon'>Zmeniť</span></a>")
Do you know how to do that?
EDIT
This is because I need to create a NEXT and PREVIOUS buttons in change object page so user can step directly to the next object.
You can just store the current request on the admin instance in the change list view to make it available to subsequent methods:
class YourAdmin(ModelAdmin):
def changelist_view(self, request, *args, **kwargs):
self.request = request
return super().changelist_view(request, *args, **kwargs)
def change(self, obj):
request = getattr(self, 'request', None)
if request:
# use request.GET to construct the link
I put together a mixin for extending AdminModels for accessing to the request parameters:
class RequestParameters_AdminMixin(object):
"""adds the request GET parameters in AdminModel variable request_parameters"""
request_parameters={}
def changelist_view(self, request, *args, **kwargs):
self.request_parameters = request.GET
return super().changelist_view(request, *args, **kwargs)
Use:
class TaskModelAdmin(RequestParameters_AdminMixin, original_TaskModelAdmin):
def column_name(self, obj):
if 'is_maintask' in self.request_parameters:
...

How can I return user ID with token in Django?

I generate tokens using default view in Django:
url(r'^login/', rest_auth_views.obtain_auth_token),
I have a problem because my front-end doesn't know what is the currently logged in user ID.
Should I return it with token or maybe create some another request?
I know that there is a lot of different ways, but I would like to choose the most optimal solution.
You could override rest_framework.authtoken.views.ObtainAuthToken.post in order to get the result you want.
myapp/views.py
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
class CustomObtainAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
return Response({'token': token.key, 'id': token.user_id})
myapp/urls.py
from django.conf.urls import url
from .views import CustomObtainAuthToken
urlpatterns = [
url(r'^authenticate/', CustomObtainAuthToken.as_view()),
]
Sample results
$ http :8000/authenticate/ username=someuser password=secretpassword
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Language: en
Content-Type: application/json
Date: Tue, 22 Mar 2017 18:30:10 GMT
Server: WSGIServer/0.2 CPython/3.5.1
Vary: Accept-Language, Cookie
X-Frame-Options: SAMEORIGIN
{
"id": 16,
"token": "82e0bc9980a6b2c9a70969b0f8dc974418dda399"
}
The idea here is to override the post method of the ObtainAuthToken view class. Here all I have done is call the parent class to get the token, then look up that token to find the associated user id.
Hope that helps.
if you need to get user information on a webpage, you need to pass user information in a response of Login API or other API.
While using Token based authentication, after login, access token and refresh token are generated which are shall be given to client in login API response. This access token shall be passed in header as:
Authorization : Bearer <insert token here>
You need to put authentication_classes = [OAuth2Authentication]
in your view.
This will validate the if user is logged in also you will get to access logged in user's information by user=request.user.
I think the good practice will be to return user details in the response of login api.
If your built_in view doesn't return user details you can may be override the post method of obtain_auth_token. I once did this for djangorestframework-jwt obtain token method
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
user = serializer.object.get('user') or request.user
token = serializer.object.get('token')
response_data = {
'token': token,
'user': UserSerializer(user).data
}
response = Response(response_data, status=status.HTTP_200_OK)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
response.data['token'],
expires=expiration,
httponly=True)
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
by default response_data dict only had token details i added user object as well to achieve what you are trying to do.
I needed more than just user id with the token, so I did code to return the whole user object:
*I use custom user, so if you are using django default user, change model and serializer to default.
from users.serializers import CustomUserSerializer
from users.models import CustomUser
class CustomObtainAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
user = CustomUser.objects.get(id=token.user_id)
return Response({'token': token.key, 'user': CustomUserSerializer(user).data})
Thanks to this thread it was easy! Hope my answer will save someones time too. :)

Categories