How to run Django views from a script? - django

I am writing a Django management command that visits a few pages, logged in as a superuser, and saves the results to a set of .html files.
Right now I'm just using the requests library and running the command with the development server running. Is there an easy way to generate the HTML from a view response so I do without actual HTTP requests?
I could create a request object from scratch but that seems like more overhead than the current solution. I was hoping for something simple.

Django has a RequestFactory which seems to suit your needs.

While it's not exactly meant for this purpose, an option would be to use the testing framework's Client to fake a request to the url - be sure to use client.login() before making your requests, to ensure you have superuser capabilities.

Related

Is separating django frontend and backend with API viable?

I'm used to Django and already developed website with a whole Django or with Django API + React.
For a side project, I'm thinking about creating a Django project with 2 apps:
Django API 2) Django Front.
I absolutely want to decouple front/back to be able to reuse the API in the future, and I like the view system from Django.
Is my idea making sense?
Edit 1:
To clarify.
App 1: Django API serving JSON.
App 2: Django App using API calls in the controllers to generate the views.
Edit 2:
I did a proof of concept and it works like a charm.
The only drawback is that I have to use Cookies to store the JWT token and maintain the session state, which is not convenient
it is possible, but completely wrong with idea.
How it possible. Wrong version:
Try to remember, how we can create integrate test for our view. We Should create client and send request to Django to your view-url with args kwargs querystring e.t.c.
In response you have already answer. Try to imagine: part with client - is your Django front, requested part - your backend.
The same works not only in test, you can create request to ask something on the completely other server.
Redis/MemCashed e.t.c. (pattern sender/receiver) Wrong version:
The Front Django speaks with Backend through Third part application. It can be faster.
"Pythonic" version. Right in your case:
You can create Backend Django part like a library with views as interfaces.
Frontend Django part is completely standalone, it import an use interfaces from library, which is your "BackEnd Module".
If you want - you can use "BackEnd Module" everywhere as import, or you can start it as server and ask info per requests.
Completely independent in this case means, you can install "BackEnd Module" without "FrontEnd Module". "FrontEnd Module" can be installed standalone too and it should take from settings, which interfaces should be used as data-source.
I hope, i am right understand your question.
You could definitely separate front and back, remember, django just creates endpoints and consumes them with its own views, you can even use both.
Here is the documentation for django views: https://docs.djangoproject.com/en/4.0/#the-view-layer
You can use a librarie like React as frontend and connect to your api(django app) and use both.

Populate web page using API result directly from API server

Firstly sorry if this question has been asked before but I'm a novice so even if it has I'm unaware of the language I'd even use to try and seek it out.
I'm beginning to learn about REST API's and it got me thinking. Is it possible to load the JSON response directly from the API server into the user's browser and bypass your own server?
Imagine you have say a Django app running on a server that accesses email messages from Outlook.com using the graph API.
I assume an ordinary flow would go something like:
User request->your server->graph api-> your server-> user browser.
It seems like a waste for it to hit your server that second time before it goes on to be presented to the user's browser.
Is there a way the Django app can render a template and effectively tell the browser "expect some data from X source, and place it in y location in this template"?
You could do that with javascript. You'd have to include either a script tag in your template, or create and include some static javascript files with the code.
I'd recommend learning and using the jQuery javascript library, as it makes what you're talking about much easier to implement. Research ajax requests, those are what you'll need to make requests directly to another server, bypassing your own

How to POST data to remote server and display result

I would like to submit some post request from my django app to payment service.
Is there a simple way to do so from within a view and then display the
remote service instead of my own view (something like being redirected to remote
page with post data)
Currently I am messing with some weird approach of displaying a hidden form and
ovveridng it's javascript submit call to implement some of my own stuff, but I think
it is overcomplicated.
I need something like this:
def view(request, **kwargs):
do_my_own_business()
post_data = create_post_dada(**kwargs)
return post_remote_page("https://example.com", post_data)
You can use python's urllib2 to to make a request to a 3rd party website. This is essentially emunlating how you or I would visit the website via code - here's a good tutorial.
If you want to make life easier, there are some libraries build upon urllib2 which make doing these external request easier - namely requests and mechanize. If you are from a PHP background you can also use pyCurl (Not based on urllib2)
Be sure that the payment service you are using doesn't have it's own API or library that you could use instead, as this would be much easier and safer then the above approach which is essentially screen scraping.
Furthermore, be aware that for every request your user makes to your server, your server needs to make to an other external server which means you could potentially time out etc. introducing another level of complexity in managing the connections.

Django: control access to "static" files

Ok, I know that serving media files through Django is a not recommended. However, I'm in a situation where I'd like to serve "static" files using fine-grained access control through Django models.
Example: I want to serve my movie library to myself over the web. I'm often travelling and I'd like to be able to view any of my movies wherever I am, provided I have internet access. So I rip my DVDs, upload them to my server and build this simple Django application coupled with some embeddable video player.
To avoid any legal repercussions, I'd like to ensure that only logged-on users with the proper permissions (i.e. myself and people living in the same household, which can, like me, access the real DVDs at their convenience), but denies it to other users (i.e. people who posted comments on my blog) and returns an HTTP 404.
Now, serving these files directly using Apache and mod_wsgi is rather troublesome because when an HTTP request for the media files (i.e. http://video.mywebsite.com/my-favorite-movie/) comes in, I need to validate against my user database that the person at the other end has the proper permissions.
Question: can I achieve this effect without serving the media files directly through a Django view? What are my options?
One thing I did think of is to write a simple script that takes a session ID and a video's slug and returns some boolean indicating if the user may (or may not) access the video file. Then, somehow request mod_wsgi to execute this script before accessing the requested URL and return an HTTP 404 if the script failed. However, I don't have a clue if this is even possible.
Edit: Posting this question clarified some of my ideas for search and I've come across mod_python's file wrapper extension. Does anyone have enough experience with that to validate that it is a viable solution?
Yes, you can hook into Django's authentication from Apache. See this how-to:
Authenticating against Django’s user database from Apache

How to simulate a HTTP Post request from a django view without a template

I am writing views, not so keen to write templates right away.
But I need to test my program by submitting post requests.
How do i simulate HTTP Post from within a django view
I am aware that urllib2 and httplib modules of python allow a lot of options, but I am looking for something that elegantly integrates into the django views.
Would U create a method that performs post, where would you call it from?
Update: Some of the answers deal with testing by sending a POST to my application. What if I want to POST to an external service and deal with POST response. How can I do it without writing templates.
Django has a built in mock Client utility that can mimic requests as if they are coming from a browser. If you don't need to fully mimic a browser and just want to invoke your views directly from your tests, consider using a RequestFactory instead.
For such cases I think RequestFactory is ideally suited.
It works just like django's test client with the difference that it let's you create a request object that you can use anywhere. So you could just create your own request object and pass it to your view or form for testing.
I like this method of testing more then using the test client, since it comes closer to pure unit testing. That is, testing a single piece of code. If you're using the test client, there are more layers added before the actual code you're testing is reached.
To avoid the pain of creating the request object yourself you can use this tip on Django snippets
It sounds like you are looking for either a unit test or an acceptance test. Take a look at unittest which is part of the standard library.
For quick ad hoc tests while developing web apps, I like to use curl. It's a simple command line tool that easily generates all sorts of HTTP requests. You can POST with a command like:
curl -i -d field=value http://localhost:8080/sample/something
Curl is available on a lot of platforms. Check it out at http://curl.haxx.se/
If you are looking at this from the context of writing unittests, you could consider creating the Request object yourself and just calling the view function directly. You could even mock it, and any other parameters the view might take.