Views and HTTPresponse with user's data - Django - python

Given a GET the url is /home/data
Where data is a value that will depend on the user, that is, the complete domain will be
domain/home/data
What I want is to return an HTTP response depending on the data value
url.py
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', home, name='home'),
]
views.py
def home (request):
response =item.objects.filter(radius<data)
return HttpResponse(response )
As you can see, radius is an attribute of the item model. And I want to filter all radius that are less than data.
How can I include data in that home function?

The path should then look like:
urlpatterns = [
path('admin/', admin.site.urls),
path('home/<int:data>/', home, name='home'),
]
such that it thus includes data as an int: You can then filter with the __lt lookup [Django-doc]:
def home(request, data):
# …
response = item.objects.filter(radius__lt=data)
# …
Of course here data needs to come from somewhere. You can not directly put item objects in a HttpResponse, a HTTP response is a stream of bytes. You can for example JSON serialize the data, or do some other encoding, but you can not use items in your response. You can for example use:
from django.core.serializers import serialize
from django.http import JsonResponse
from json import loads
def home(request, data):
response = item.objects.filter(radius__lt=data)
data = serialize('json', response)
return JsonRespnse({'data': loads(data)})

You would capture it from the URL like this
path('home/<data>/', home, name='home'),
You can get it in the view with
def home(request, data=None):

Related

Unable to retrieve a single item when through HTTPRequest with Django Rest

I follow the instructions on Django Restframework tutorial here and has configured everything after it, but somehow, I can't use id to retrieve the json for a single item.
I expect to get a json representation of a single item when i request localhost:8080/items/[index], but instead of getting the item with the corresponding index I would get json representation of every items in I have.
My views.py
#api_view(['GET'])
def item_list(request):
"""
List and create items
"""
if request.method == 'GET':
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
return Response({'data': serializer.data })
#api_view(['GET'])
def item_detail(request, pk):
"""
Retrieve an item
"""
try:
item = Item.objects.get(pk=pk)
except Item.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ItemSerializer(item)
return Response(serializer.data)
My urls.py in item module
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'$', views.item_list),
url(r'^items/(?P<pk>[0-9]+)/$', views.item_detail),
]
My urls.py in app module
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^', include('menu.urls')),
]
Edit: Thanks for the reply but it I think I have found a fix. It seems like by putting 'url(r'$', views.item_list)' in front all links will reroute to item_list(). The easy fix is just put it behind 'url(r'^items/(?P[0-9]+)/$', views.item_detail)'
switch the url paths in your url.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^items/(?P<pk>[0-9]+)/$', views.item_detail),
url(r'^$', views.item_list),
]
and include like
urlpatterns = [
path('admin/', admin.site.urls),
url(r'', include('menu.urls')),
]

Django Write Authentication Redirect for Blackboxed Route URLs

I'm using a django library called django-dashing that has a predefined set of urls that render a dashboard. I import them like this
urlpatterns = [
...
url(r'^dashboard/', include(dashing_router.urls)),
...
]
I want the router to be accessible only by administrators, which I can do with some config settings within django-dashing. However, when a non-admin user attempts to access /dashboard/, I want to redirect them to django's /admin/ panel to have them log in, instead of throwing the 403 that django-dashing does.
Since the django-dashing views are effectively blackboxed, I was wondering if there was a way to write a 'pre-view' that would intercept the request to /dashboard/, run some code – specifically, doing the appropriate redirects – and then continue onto the actual dashboard.
I know this would be easy enough to do by writing two urls, like /dashboard-auth/ which redirects to /dashboard/, but I don't want the user to have to go to one URL to get to another
Any suggestions?
A Django simple custom middleware is another option...
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class DashingRedirectMiddleware(object):
def process_request(self, request):
if request.path.startswith('/dashing/') and not request.user.is_staff:
return HttpResponseRedirect(reverse('admin:login'))
return
Don't forget to add this middleware to your DJANGO SETTINGS...
MIDDLEWARE_CLASSES = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'yourapp.middleware.DashingRedirectMiddleware',
...
]
Or something like that.
The way I would do it is by overridding dashing's default router. All of the urls are generated dynamically by the Router class, so by overriding the get_urls method, you can wrap each function in the staff_member_required decorator.
from django.contrib.admin.views.decorators import staff_member_required
from django.conf.urls import url
from dashing.utils import Router
from dashing.views import Dashboard
class AdminRequiredRouter(Router):
def get_urls(self):
urlpatterns = [
url(r'^$', staff_member_required(Dashboard.as_view()), name='dashboard'),
]
for widget, basename, parameters in self.registry:
urlpatterns += [
url(r'/'.join((
r'^widgets/{}'.format(basename),
r'/'.join((r'(?P<{}>{})'.format(parameter, regex)
for parameter, regex in parameters.items())),
)),
staff_member_required(widget.as_view()),
name='widget_{}'.format(basename)),
]
return urlpatterns
router = AdminRequiredRouter()
Then include your router instead of dashing's
from .router import router
urlpatterns = [
...
url(r'^dashboard/', include(router.urls)),
...
]
If you are willing to look inside the 'black box' of the dashing urls, you can see that the /dashboard/ is handled by the Dashboard view. You could subclass this view, and catch the PermissionDenied error.
from django.core.exceptions import PermissionDenied
from dashing.views import Dashboard
class MyDashboard(Dashboard):
def get(self, request, *args, **kwargs):
try:
return super(MyDashboard, self).get(request, *args, **kwargs)
except PermissionDenied:
return redirect('/admin/')
Then add your view above the dashing urls:
urlpatterns = [
...
url(r'^dashboard/$', MyDashboard.as_view())
url(r'^dashboard/', include(dashing_router.urls)),
...
]

Django views and URl's

I'm having a problem with the way my URL's look in Django. I have a view like this:
def updatetext(request, fb_id):
Account.objects.filter(id=fb_id).update(display_hashtag=request.POST['hashtag'])
fb = get_object_or_404(Account, pk=fb_id)
return render(request, 'myapp/account.html', {
'success_message': "Success: Settings updated.",
'user': fb
})
When a user clicks on the URL to update the text they are then redirected to the account page but the URL then looks like 'account/updatetext/'. I would like it just be 'account/'.
How would I do this in Django. What would I use in place of render that would still allow me to pass request, 'success_message' and 'user' into the returned page but to not contain the 'updatetext' within the URL?
[edit]
The urls.py file looks like this:
from django.conf.urls import patterns, url
from myapp import views
urlpatterns = patterns('',
url(r'^home/$', views.index, name='index'),
url(r'^(?P<fb_id>\d+)/$', views.account, name='account'),
url(r'^(?P<fb_id>\d+)/updatetext/$', views.updatetext, name='updatetext'),
url(r'^(?P<fb_id>\d+)/updatepages/$', views.updatepages, name='updatepages'),
url(r'^login/$', views.user_login, name='login'),
url(r'^logout/$', views.user_logout, name='logout'),
url(r'^admin/$', views.useradmin, name='admin'),
)
You need to actually redirect the user to '/account/'. Rather than returning a call to render you can do the following:
from django.http import HttpResponseRedirect
def updatetext(request, fb_id):
Account.objects.filter(id=fb_id).update(display_hashtag=request.POST['hashtag'])
fb = get_object_or_404(Account, pk=fb_id)
return HttpResponseRedirect(reverse('account', kwargs={"fb_id": fb_id}))
However, it would be better to pass in a call to reverse into the HttpResponseRedirect constructor, but since I don't know your urls.py I just wrote the relative url.

Django URL Routing Issue

Very new to Django, so I apologize as I'm sure this has an easy answer.
I have a PHP background, and so I guessing that I am trying to force a structure I am used to, and not one that is native in Django.
Here is my Project's urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('pm.urls', namespace='pm')),
)
Here is my App's urls.py
from django.conf.urls import patterns, url
from pm import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^label/add/$', views.add_label, name='label_add'),
)
I am doing an AJAX Post request to /label/add/, but it's coming back with a 500 error.
This is the views.py:
from django.shortcuts import render
from pm.models import Label
import json
# Create your views here.
def index(request):
labels_list = Label.objects.order_by('name')
return render(request, 'pm/index.html', {
'labels' : labels_list
})
""" Labels """
def add_label(request):
if request.is_ajax():
response = {
'success': True
}
else:
response = {
'success': False,
'error': "Invalid request"
}
return json.dumps(response)
Any advise or references would be great.
UPDATE
Here's the first couple of lines from the traceback I am getting:
AttributeError at /label/add/
'str' object has no attribute 'get'
you have to return HttpResponse instead of string:
return HttpReponse(json.dumps(response), content_type='application/json')

Django; Will not make the correct request

I am just beginning to learn how to use django. I have set up my views.py, urls.py, settings.py, and relative HTML pages. I am able to get the index page to come up but not the about page (only outputs some text) or my category page. I am assuming that the problem is affecting them both.
Views.py:
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
from rango.models import Category
from rango.models import Page
def index(request):
# Obtain the context from the HTTP request.
context = RequestContext(request)
category_list = Category.objects.order_by('id')[:5]
context_dict = {'categories': category_list}
# Render the response and send it back!
return render_to_response('index.html', context_dict, context)
def about(request):
# Request the context of the request.
# The context contains information such as the client's machine details, for example.
context = RequestContext(request)
context_dict = {'boldmessage': "I am from the context"}
return render_to_response('/about.html', context_dict, context)
def category(request, category_name_url):
# Request our context from the request passed to us.
context = RequestContext(request)
category_name = category_name_url.replace('_', ' ')
context_dict = {'category_name': category_name}
try:
category = Category.objects.get(name=category_name)
pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
context_dict['pages'] = pages
context_dict['category'] = category
except Category.DoesNotExist:
# Go render the response and return it to the client.
return render_to_response('rango/category.html', context_dict, context)
urls.py:
from django.conf.urls import patterns, url
from rango import views
# At the top of your urls.py file, add the following line:
from django.conf import settings
urlpatterns = patterns('',
url(r'$', views.index,name='index'),
url(r'about/$', views.about,name='about'))
#url(r'category/$', views.category,name='category'))
# UNDERNEATH your urlpatterns definition, add the following two lines:
if settings.DEBUG:
urlpatterns += patterns(
'django.views.static',
(r'media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )
My template directory has been hard coded so it really shouldn't be a problem
TEMPLATE_DIRS = ('C:/Users/aharon/Desktop/TEMP',)
Keep in mind that I am very noob so please be easy on me and I would like as much explanation as possible. Thank You!
You have not anchored your regexes with ^ at the start. Without that, your first pattern will match every single URL. You should makes sure they all start with ^.

Categories