I have an application created long back, now client want to expose its some of views as APIs without breaking existing functionality, so that they can directly consume APIs using REST Tools to see the reports.
Is there any easier way, I can convert my function to a REST View.
P.S - I kept code shorter here to keep question simple, but in fact, its much complex in the actual app.
eg.
URL : -
`path('/users', views.show_user_details, name='users'),`
VIEW
def show_user_details(request, user_id):
users = User.objects.all()
return render(request, "Users.html", {"users":users})
In REST Views, I want it to convert its input and output so that it can be accessible with same urls(or with little modifications), without much updating the existing views.
`path('rest/users', views.show_user_details, name='users'),` #-- I am ok to add new url like this, but without much change in existing view .
def show_user_details(request, user_id):
users = User.objects.all()
return JsonResponse({"users":users})
Due to the fact that a normal website visit is still a GET request and GET is just one of your usual REST actions, you'll probably want to prepare your own independent API endpoint. Check out django-rest-framework for that, and you might just feel at home for this task.
Related
I'm creating a pretty large Django application and the whole front end works by making Javascript API calls to the back end and rendering the data, my only concern is the API I'm writing will also be used by other users from the command line or their own apps.
For front end to back end I'm just doing
if request.user.is_authenticated:
# Do shit
# Return Said shit but with JSON
How do I program in a way that this also works in a token based way? Or should every user have a default token that's used to make this API call?
How does a app like gcloud do this, I could pass objects to the django template, but I'm giving select options that make heavier API calls in the frontend. If there's a way I can move forward with this approach help will be much appreciated, and advice will be even more appreciated.
So I have a django app with some models which I can manipulate via admin and also through a client facing site, like add instances etc. However, I would like to try something a little different from that. I have a Python script that uses POST and JSON objects based on those self same models and I would like to be able to run it, connect to my django app server via a port and create new instances of my models (essentially without using Admin or my client page). Any ideas how I go about this?
If what the script does is simple, it may be easiest just to create a view which receives the JSON, processes it, and returns a JsonResponse.
e.g.
def create_object(request):
if request.method == 'POST':
data = json.loads(request.body)
# Do something with the data - e.g. create a model instance
MyModel.objects.create(**data)
return JsonResponse({'status': 'created'})
Alternatively, if the script does more complicated things or if you intended to expand it in future, you may be best to expose your site via a REST API using something such as Django Rest Framework.
With Django Rest Framework, you can fairly rapidly build CRUD based APIs around your models using components such as ModelViewSets and ModelSerializers and expose them over REST with minimal code.
I'm using django rest framework and trying to save some data so it will be accessible by GET, PUT, DELETE.
So when user send GET request server send some information (a random number, for example) and that information is needed after user sends PUT request on the same url. How would one save such information? I'm using class-based views.
So i want to save that information on GET method.
I tried saving that information to class variable self.information, but the problem is self.information is empty when PUT method is getting called.
I also tried saving it to session, but like class variable, session is also empty when PUT method is being executed.
class SampleClass(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, generics.GenericAPIView):
serializer_class = SampleSerializer
def get(self, request):
random_number = random.randint(0, 10)
request.session['number'] = random_number;
content = {'random_number': random_number}
return Response(content)
def put(self, request):
number = request.session['number'] # key doesn't exists
process_number(number)
# ...
Before I begin, it's important to note that HTTP is a stateless protocol, and you are looking to add state into the mix. If you can rework what you are doing to not depend on previous requests, that will probably be better in the long run.
I tried saving that information to class variable self.information, but the problem is self.information is empty when PUT method is getting called.
This is because the class is re-initialized for each request. Because of that, the class variables don't persist across requests. Even if they did, that would mean everyone would get access to the persisted value, and it isn't made clear if that is what you are looking for.
I also tried saving it to session, but like class variable, session is also empty when PUT method is being executed
This doesn't work because Django sessions are persisted through the use of cookies. While this might work for SessionAuthentication, it won't work for any authentication that happens outside of the browser. This is because the session cookies won't be included, so Django will think the new requests are under a different session.
Now, just because HTTP is mostly stateless and doing this might lead to future trouble, that doesn't mean that you should never do it. The Django sessions wouldn't exist if there wasn't a need for it, and there are ways to save state without Django sessions.
Create a new model for the state - This is usually the best way to save state per-user and ensure that it doesn't fade away. The model needs a user field along with the fields that the state will be stored in, and all you need to do is have a query that retrieves the state object for the user.
Use the Django cache - This is the way I would recommend it for the case that you specified in your question. When you don't need to store much state, the state is shared among everyone, or you can live with it not existing (expiring), storing the data in a simple cache environment will probably work the best. You have much more control over what is stored, but at the expense of having to do more work.
I have built an API with Django Rest Framework. I want to change pagination for a better user experience.
The problem:
The client makes a call to request all posts. The request looks like:
http://website.com/api/v1/posts/?page=1
This returns the first page of posts. However, new posts are always being created. So when the user requests:
http://website.com/api/v1/posts/?page=2
The posts are almost always the same as page 1 (since new data is always coming in and we are ordering by -created).
Possible Solution?
I had the idea of sending an object id along with the request so that when we grab the posts. We grab them with respect to the last query.
http://website.com/api/v1/posts/?page=2&post_id=12345
And when we paginate we filter where post_id < 12345
But this only works assuming our post_id is an integer.
Right now I'm currently only using a basic ListAPIView
class PostList(generics.ListAPIView):
"""
API endpoint that allows posts to be viewed
"""
serializer_class = serializers.PostSerializer # just a basic serializer
model = Post
Is there a better way of paginating? so that the next request for that user's session doesn't look like the first when new data is being created.
You're looking for CursorPagination, from the DRF docs:
Cursor Pagination provides the following benefits:
Provides a consistent pagination view. When used properly CursorPagination ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.
Supports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.
You can also use -created as the ordering field as you mentioned above.
How about caching the queryset? So that the next page is served from the same query set, and not from a new one. And then you could use a parameter to get a new queryset when you want.
Something like this:
from django.core.cache import cache
class PostList(generics.ListAPIView):
def get_queryset(self):
qs_key = str(self.request.user.id) + '_key'
if 'refresh' in self.request.QUERY_PARAMS:
# get a new query set
qs = Post.objects.all()
cache.set(qs_key, qs)
return cache.get(qs_key)
So basically, only when your url will be like this:
http://website.com/api/v1/posts/?refersh=whatever
the request will return new data.
UPDATE
In order to provide each user with it's own set of posts, the cache key must contain an unique identifier (which might be the user's ID):
I also updated the code.
The downside to this approach is that for a very large number of users and a large number of posts for each user, it might not work very well.
So, here is my second idea
Use a TimeStamped model for the Post model, and filter the query set based on the created field.
I don't know much about your models and how exactly they are built, so I guess you will have to choose which solution is best for your app :)
Maybe you can add a field to every object like "created_at/updated_at". Then you can save the timestamp when the user made the request and filter out everything that came after it.
Haven't tried it myself but I guess it might work on your case
Is there an online resource that shows how to write a simple (but robust) RESTFUL server/client (preferably with authentication), written in Python?
The objective is to be able to write my own lightweight RESTFUL services without being encumbered by an entire web framework. Having said that, if there is a way to do this (i.e. write RESFUL services) in a lightweight manner using Django, I'd be equally interested.
Actually, coming to thing of it, I may even PREFER a Django based solution (provided its lightweight enough - i.e. does not bring the whole framework into play), since I will be able to take advantage of only the components I need, in order to implement better security/access to the services.
Well, first of all you can use django-piston, as #Tudorizer already mentioned.
But then again, as I see it (and I might be wrong!), REST is more of a set of design guidelines, rather than a concrete API. What it essentially says is that the interaction with your service should not be based on 'things you can do' (typical RPC-style methods), but rather 'things, you can act on in predictable ways, organized in a certain way' (the 'resource' entity and http verbs).
That being said, you don't need anything extra to write REST-style services using django.
Consider the following:
# urlconf
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('',
url(r'^tickets$', 'myapp.views.tickets', name='tickets'),
url(r'^ticket/(?P<id>\d+)$', 'myapp.views.tickets', name='ticket'),
url(r'^ticket$', 'myapp.views.tickets', name='ticket'),
)
# views
def tickets(request):
tickets = Ticket.objects.all()
return render_to_response('tickets.html', {'tickets':tickets})
def ticket(request, id=None):
if id is not None:
ticket = get_object_or_404(Ticket, id=id)
if request.method == 'POST':
# create or update ticket here
else:
# just render the ticket (GET)
...
... and so on.
What matters is how your service is exposed to its user, not the library/toolkit/framework it uses.
This one looks promising. http://parand.com/say/index.php/2009/04/30/django-piston-rest-framework-for-django/ I've used it before and it's pretty nifty. Having said that, it doesn't seem maintained recently.