How add variable to django request from my front-end? - django

I am developing web app, with djangorestframework on the back and Vue.js on the front. Interface was translated to a few language. On the site footer user can see icons of language represented country flag.
After hit the need icon, app translate all text to required language. All actions for translate do in front and my backend know nothing about what is language was chosen. Now I want to tell my back-end about chosen language, how can I do it? I think to add a variable language to my django request object, but I can find nothing about it.
Any ideas?

I see two approach :
Send the language value on every (interesting) request, as you proposed
Or, keep it in user settings in the backend : you add a charfield on a custom user model. When you need the language value during a request, you can access it through self.request.user.lang. You will have to add a route to update the value when users click on the icons.
It depends on how usual the language value is needed ; if its often, it will be simpler to have it in the backend. But you must keep the value up to date... Its a trade off :)

I specified a language variable in my localStorage then I returned value to Content-Language header and after this I've could take the language value in my django request.

Related

How to build conversational form with django?

I am trying to build a conversational form with Django.
It will be used in landing page. The form questions will be loaded one by one as user answers them. And there will be some greeting and "human-way" responses to user input (such as "wow! you did a good choice!" after user selects one of the choices from form). The experience and look of the app will be like a real-time chat but user can only select one of the choices from form or upload a file/image.
1. Which technology is better to use for it? I am planning to do it with Fetch.
2. Since I want it to work without page reloading, how do I need to load Django forms through Fetch? Do I need to pass elements of it with JSON and construct it in client-side or can I just pass it as an html with {{form.as_p}} and display it in HTML?
Does these options make difference in matter of security?
I do not know anything about Fetch, but anyway I think it must be constructed clientside, but at first I would simply display the form in a template to get the ids of its fields and then use it in clientside code.
What about security - you'll need to pass the csrf token via your form.

Django: which url does the LocaleMiddleware check?

Our company provides both a API and a small number of widgets that are embedded in clients websites through Iframes.
Now we have a Belgian customer who wishes to use our widgets. As you know Belgium is bi-lingual, so we are making liberal use of both the LocaleMiddleware and the {% trans 'string' %} tags.
Now as I understand correctly the middleware checks the URL to see which language to use. When you first visit our clients website you get a large pop-up where you choose your language. After this popup your url changes to this format: www.clientorg.be/fr_BE/rest-of-the-url, so that should (hopefully) work just fine.
However, our widget is served through an Iframe. (src = s2.oururl.com) which contains no language value.
So my question is: Will Django be able to detect the language of the user? Or will it only be able to check 'our' s2.url, meaning we need to contact our client and provide him with 2 urls to paste in the iframe, depending on the language the user chooses.
Here's exactly what LocalMiddleware tries to do to determine the language:
https://docs.djangoproject.com/en/2.0/topics/i18n/translation/
LocaleMiddleware tries to determine the user’s language preference by
following this algorithm:
First, it looks for the language prefix in the requested URL. This is
only performed when you are using the i18n_patterns function in your
root URLconf. See Internationalization: in URL patterns for more
information about the language prefix and how to internationalize URL
patterns.
Failing that, it looks for the LANGUAGE_SESSION_KEY key in the current
user’s session.
Failing that, it looks for a cookie.
The name of the cookie used is set by the LANGUAGE_COOKIE_NAME
setting. (The default name is django_language.)
Failing that, it looks at the Accept-Language HTTP header. This header
is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
Failing that, it uses the global LANGUAGE_CODE setting.

User controlled presentation of data in widgets on a dashboard app - Best Practices?

Consider a very simple dashboard application in Django. It has 2 models:
Page
Widget
Naturally, Page and Widget have a ManyToMany relationship.
Like any good dashboard implementation, the designers can change 3 things in a widget:
Data source that drives the widget
Placement of widget on the Page
Presentation of Data inside a widget
The Data is specified using a URL field in the Widget and is being served by a REST API based on Django REST Framework with the django-filter backend.
The Placement on the Page is catered using the excellent Gridster.
This leaves the Presentation part. I have two possible solutions:
Attach a template TextField with the Widget. Data will be fetched from web services in JSON format and rendered according to the template (handlebars) defined in Widget on the client side.
Pass the template name as query string in the URL to the REST API and render the Data using the user-specified template.
Now that the context is clearly defined (hopefully), following are my questions:
Is there any way I can choose the first solution and still be able to use the automatic forms generated by the DRF Serializers?
If not, and I choose the second solution, are there any potential pit-falls regarding security, code maintenance, code quality, testing and the like? Why have I not seen anyone else doing this i.e. letting the user select the template via query string?
Is there any other solution that I am missing?
Your first options seems most promising: fetch the data as JSON and insert it into templates on the client. All good.
So can you do that "and still be able to use the automatic forms generated by the DRF Serializers"? — Short answer, it depends what you mean by "automatic forms".
Serializers take a data dictionary, validate it and (for ModelSerializer subclasses) convert it into a (model) object instance for you. If by "automatic forms" you mean will you still be able to this validation behaviour, then the answer is yes. Create your JSON payload on the client and send an appropriate HTTP request to the API. Django Rest Framework's Serializers will work as expected.
If (though) by "automatic forms" you mean will you still be able to use the HTML forms that DRF provides in its web broweasble API, then the answer is no. The browseable API is built around an HTML renderer returning entire web pages. These include a pretty-printed representation of the JSON you'll be using as well as the web-forms that, on this assumption, you're interested in.
If you go this route you'll need to generate the forms on the client, using whatever model, view, template and binding features your chosen library (libraries?) offer(s).
I hope that helps. Good luck.

Django Internationalization with Geolocation

From what I read in Django documentation, this is what LocaleMiddleware does:
LocaleMiddleware tries to determine the user’s language preference by following this algorithm:
First, it looks for the language prefix in the requested URL. This is
only performed when you are using the i18n_patterns function in your
root URLconf. See Internationalization: in URL patterns for more
information about the language prefix and how to internationalize URL
patterns.
Failing that, it looks for a django_language key in the current user’s
session.
Failing that, it looks for a cookie.
The name of the cookie used is set by the LANGUAGE_COOKIE_NAME
setting. (The default name is django_language.)
Failing that, it looks at the Accept-Language HTTP header. This header
is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
Failing that, it uses the global LANGUAGE_CODE setting.
I want my django project to detect user country and use it in choosing default language?
How to do this:
I have two ideas in mind:
Write a new middleware which to execute before LocaleMiddleware and in this middleware if there is no cookie LANGUAGE_COOKIE_NAME to set it using django GeoLocation
Replace LocaleMiddleware and instead of looking for Accept-Language HTTP header to use django GeoLocation
What do you think?
Or may be there is another easier way?
Edit: I will have an option for changing language, the problem is only when you open the website (any page, not just front page) for the first time. I'm considering now to set django_language for the default website language /bg/ (if there is no such settings) and also use international urls /en/, /bg/. Also there have to be a language switch option. This way there will be no problem with search engines and I will not use geolocation at all.
Edit: Also there is this problem that here (in Bulgaria) most browsers headers are set to prefer English language which is not a good option :(
Actually it isn't a very good idea overall. You should rarely want to set a language for a client, that's why most sites use an optional language form. (flag buttons or possibly a dropdown select).
The LocaleMiddleware runs down a hierarchical path that most likely will pick the right translation (if available). A proper solution would be to hand your clients a form to set or switch their preference. You could populate the django_language session key if the form is processed.
Also crawlers will not scrape pages properly if forced to a language setting.
I found this, that is very usefull:
Middleware that will force django to use settings.LANGUAGE_CODE for default language and not use equest.META['HTTP_ACCEPT_LANGUAGE']
class ForceDefaultLanguageMiddleware(object):
"""
Ignore Accept-Language HTTP headers
This will force the I18N machinery to always choose settings.LANGUAGE_CODE
as the default initial language, unless another one is set via sessions or cookies
Should be installed *before* any middleware that checks request.META['HTTP_ACCEPT_LANGUAGE'],
namely django.middleware.locale.LocaleMiddleware
"""
def process_request(self, request):
if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
del request.META['HTTP_ACCEPT_LANGUAGE']
Source: https://gist.github.com/vstoykov/1366794

Access session / request information outside of views in Django

I need to store a special cookies that is coming from some non-django applications. I can do this in views
request.session[special_cookies'] = special_cookies
But in the non-views py files, I need to access this special cookies.
According to docs, I can do this
>>> from django.contrib.sessions.backends.db import SessionStore
>>> import datetime
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10)
>>> s['last_login']
datetime.datetime(2005, 8, 20, 13, 35, 0)
>>> s.save()
If I don't supply the session key, Django will generate one for me.
I am concerned about the effect of getting many new session keys. (I don't think this is good when you have multiple users, right...?)
I want a user to have this special cookies binded to a user's session. However, I do not want to save this in a user profile, because for security reason. This cookie is generated when we login (our application will send in this special cookies). We want to send this cookie back and forth throughout the browsing session.
How should I go about solving this?
Thank you very much!
#views.py
request.session['special_cookies'] = library.get_special(user, pwd)
#library.py
def get_special_cookies(user, pwd):
res = get_special_cookies("http://foobar.com/api/get_special_cookies", user, pwd)
#foobar.py (also non-views)
def do_this(user, special_cookies)
I am pretty sure this is fine....
#views_2.py
def dummy_views(request):
foobar.do_this(request.user, request.session['special_cookies'])
But there are instances where I don't want to get my special cookies through views / calling get_sepcial_cookies. I want it to last throughout. Or am I overthinking..?
In order to explain why you are in a dangerous path, we have to remember why server side sessions where invented in the first place:
HTTP is a stateless protocol. A stateless protocol does not require the server to retain information or status about each user for the duration of multiple requests. For example, when a web server is required to customize the content of a web page for a user, the web application may have to track the user's progress from page to page. A common solution is the use of HTTP cookies. Other methods include server side sessions, hidden variables (when the current page contains a form), and URL-rewriting using URI-encoded parameters.
Django is a very mature framework; if some goal seems hard to accomplish in Django, probably you are taking the wrong approach to the problem. Even if you can store server side session information directly at the session backend, it seems like bad design for me, because session data is not relevant outside requests.
IMHO, if you need to share authentication/authorization data among applications, you should really consider something like OAuth, otherwise you will end up with something insecure, fragile, ugly and hard to support.
(sorry if I sound condescending, English is not my native idiom).
[update]
Hi Paulo. Thank you very much. I believe my team doesn't want to introduce OAuth or any sort of extra layer of authetication mechaicism. But are you against inserting this special cookies into HttpResponse.COOKIES?
A few remarks if you you really want to go this way:
you will be constrained by the "same domain" restriction (the other application should reside in the same TLD)
you should use some sort of signing to avoid tampering with the cookies
Is that a better solution than request.session?
There are some mechanisms to deal with this kind of problem at a higher level. For example:
if you want to make a variable present at every template context based on the value of some cookie, you can write a custom context processor.
if you want to reroute views depending on the presence of a cookie, you should write a custom middleware.
I can't provide a more specific solution without further details about your goals, but using these hooks you can avoid repeating code to test for the external cookie in every view - note however that everything concerning cookies is tied to the request/response context and makes no sense outside it.