How to access request object of django in react? - javascript

I have multiple apps in my Django project but for One app I would like to use react, so I have create two apps one for apis and other for frontend.
I used webpack to merge django and react.
Now I want to access request.user and user.is_authenticated in my components.
How can I access those without calling apis as I am not using token-based authentication so I can not call APIs.
views.py
def index(request):
return render(request,'index.html')
urls.py
urlpatterns = [
re_path(r'^(?:.*)/?$',index),
]
I would like to use is_authenticated in my sidebar everywhere.

You can just pass the request user and is_authenticated to the context of the index view and access it in your React components via the window object.
In your views.py:
def index(request):
context = {
'user': request.user,
'is_authenticated': request.user.is_authenticated,
}
return render(request, 'index.html', context)
In your index.html:
<script>
window.user = {{ user|safe }}
window.is_authenticated = {{ is_authenticated|safe }}
</script>

Related

Multi-Language website using Django JS, facing error on Search filter error

I'm building a multi-language Django site and using 'Django-parler' for my model data translations. Now I'm wondering if there is a Django search app that works with multi-language models and I used to create the search functionality here, it works fine for single-language sites. But, I can't get it to work with multiple language filter functions.
Here is my models.py
from django.db import models
from parler.models import TranslatableModel, TranslatedFields
class Category (TranslatableModel):
translations = TranslatedFields(
category_Title=models.CharField(max_length=500)
)
def __str__(self):
return self.category_Title
class Faq_QA(TranslatableModel):
translations = TranslatedFields(
question_Title=models.CharField(max_length=500),
question_Description=models.TextField(),
category_Option=models.ForeignKey(Category, on_delete=models.CASCADE),
SEO_Keywords=models.TextField(),
)
def __str__(self):
return self.question_Title
Here is my search View.py
from django.shortcuts import render
from .models import Category, Faq_QA
from django.db.models import Q
# Create your views here.
def base(request):
if 'q' in request.GET:
q = request.GET['q']
multiple_keywords_faq = Q(Q(question_Title__icontains=q) | Q(question_Description__icontains=q))
search_key_faq = Faq_QA.objects.filter(multiple_keywords_faq)
else:
search_key_faq = Faq_QA.objects.all()
context = {
'search_data': search_key_faq,
'category_data': Category.objects.all(),
}
return render(request, 'Base.html', context)
For references my error-throwing image is here;
Multi-Language website Error on Search filter image is here - please refer to it
Can anyone please help me with this error,

How to redirect to a specific page of Vue-app via Flask

I'm building an app that has a page which ends in '#' provides some meta info for the page without '#', for example if the page '/user/aabb' has info about the user 'aabb', then the page '/user/aabb#' is the meta page for that user.
The problem is, '/aabb' part doesn't really exist because the app is SPA. 'aabb' is simply delivered as a prop for the component used in '/user' routing. Nor I can directly access '/user/aabb#' in the same context.
So is there a way for Flask to render a specific page of a Vue-build app? so that if the user enters '/user/aabb' on the address bar it links into '/user' page with 'aabb' prop. If there is, I guess the following functionalities should be required.
Flask to redirect to a specific page inside of Vue-route.
Flask to send data to the vue-component of that page.
Vue to receive the data from Flask.
Or is there any other ways to solve this... issue?
Thanks in advance.
The solution to all your questions is to use Vue Router with HTML5 History Mode.
As I mentioned in your last question, set up your Flask app to use the Vue SPA as the front-end
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def catch_all(path):
return app.send_static_file("index.html")
Then set up a router for your front-end URLs
// router.js
import Router from "vue-router"
import Vue from "vue"
Vue.use(Router)
export default new Router({
base: "/", // this should match the root path for your app
mode: "history",
routes: [{
name: "UserMeta",
path: "/user/:username#",
component: () => import("./path/to/UserMeta.vue"),
props: true
}, {
name: "User",
path: "/user/:username",
component: () => import("./path/to/User.vue"),
props: true
}]
})
You have to make the #-suffixed meta routes are listed before the normal pages in order to guarantee it doesn't think the username ends in #. See Matching Priority.
In the example above, both components receive the username route parameter as a prop.
You can then use one of the Data Fetching methods to load data into your components from your Flask API when your routes are loaded.
For example, using Fetching After Navigation and assuming you have a Flask app route for /api/user/<username>...
<template>
<div>
<div v-if="user">
<!-- show user details here -->
</div>
<div v-else>Loading...</div>
<//div>
</template>
<script>
export default {
name: "User",
props: { username: String },
data: () => ({ user: null }),
async created () {
const res = await fetch(`/api/user/${encodeURIComponent(this.username)}`)
this.user = await res.json()
}
}
</script>

Pass data from blade file directly to Vue instance

I am working on a Vue application that's living in a Laravel project. I bind my vue instance to an id that's placed in a blade file.
What I would like to do is to pass the logged user to my Vue instance from Laravel/blade. Is there a way to do this? I know you can pass data through props but this here is just a regular div with an id of #root that's binding the Vue instance. I know how to get the logged user, but I am specific looking for an way to directly pass the data from blade to my vue instance.
app.js
// Require the deps from laravel (jQuery, axios, Bootstrap)
require('./bootstrap');
// Import vue deps
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter)
// Import the router & routes
import router from './routes'
// Init a new vue instance
const root = new Vue({
el: '#root',
data: {
User: name here..
},
router
});
Blade
#extends('layouts.app')
#section('content')
<!-- pass user below -->
<div id="root"></div>
#endsection
In your blade file, pass the logged user information to a javascript global variable. Let's say you just want the user id and name:
<script>
window.auth_user = {!! json_encode([
'id' => auth()->user()->id,
'name' => auth()->user()->name
]) !!};
</script>
Then in your javascript, you can access the auth_user global variable.
For example, to log the user name:
console.log(auth_user.name)
or
console.log(window.auth_user.name)
You have few options (I think I not list all) e.g:
You can pass data by converting them to json and write as HTML element or attribute and then read it from vue using e.g. document.querySelector(...) - more info here: Best way to store JSON in an HTML attribute?
You can change a littlebit architecture and create separate (Restful) API which your vue components will be use via ajax to read data (e.g. you can create GET api/v1/currentUser do read current logged user)
Completly change your architecture - to "microservices" - so in laravel only create Restful API, and creatte SEPEARATE project with vue (and NO laravel) user interface which use that API (it is modern approach to separation backend from frontend). You will face CORS problem in this approach but its no so hard (only at first time).
You might want to take a look at the PHP-Vars-To-Js-Transformer
package. You can use it either in your controller or in a #php directive.
Probably not a good practice with VueJS though.

react: how to pass in URLs for REST APIs

Starting to learn react and couldn't find the answer to this on the internet. Maybe I don't know what terms to use.
My backend is django and I want to be able to pass in URLs for REST APIs to my React front end.
I don't want to hard code them in react as they are already defined in django.
It makes sense to me that I would want to render a script tag on my html template that contains an object containing the URL values.
e.g. the django template would have something like
<script type="text/javascript">
var CONFIG = {
some_url : '{% url "my-api" %}'
}
</script>
(for those not familiar with django, that {% url %} tag renders a url like /path/to/myapi)
Then in my React Stores/Actions I would just refer to CONFIG.some_url.
Is this the right way to do it? Or is there a better way to make this information available to my react components.
------------ Edit -----------------
Using webpack to transpile the jsx files and using django-webpack-loader to integrate everything. this means that the django templates are completely rendered before the jsx is loaded on top.
As a result the template tags cannnot run inside the jsx files.
Even though you're using django-webpack-loader(I am too), you still can pass props to your React app. You can proceed like this:
1) Resolve the absolute backend url in your view.py:
def get_context_data(self, **kwargs):
context['APIROOT_URL'] = reverse('api-root', request=self.request)
return context
2) Pass the context prop to the html template
<div id="react-app"></div>
<script>
window.__APIROOT_URL__= '{{ APIROOT_URL }}';
window.react_mount = document.getElementById('react-app');
</script>
{% render_bundle 'main' %}
3) Finally inside your app, get the property like this:
const apirootUrl = window.__APIROOT_URL__
pass it as props:
<MyComponent src={% url %} />
Put following plugin in your webpack configuration:-
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.environ),
}
})
],
Run the webpack command as follows:-
environ=local webpack
or
environ=production webpack -p //for production
Create a constants file where you keep a function which returns API
urls based on environment variable set above.(local,dev,production).
const api_url=function(){
let api_url=//production api url
if(process.env.NODE_ENV == 'local'){
//local api url
}
else if(process.env.NODE_ENV == 'development'){
//dev api url
}
return api_url;
}
export const url= api_url();
Import this in your componentDidMount() call the api using ajax/fetch/axios
import {url} from ../constants
componentDidMount(){
//api call
}
If you are using django and react together I would strongly suggest to look at django-webpack-loader once

Django: static file image URL paths breaks except for main page template

I'm trying to setup my static file in development. I have an image located in polls/static/images/banner.jpg. When I navigate to 127.0.0.1:8000/ the banner shows up, but when I go to something like 127.0.0.1:8000/2ndpage the banner breaks.
my index (URL: 127.0.0.1:8000/) template contains:
{% include 'polls/header.html' %}
The URL for the banner http://127.0.0.1:8000/static/images/banner.jpg
my 2ndpage template also contains:
{% include 'polls/header.html' %}
But the URL for the banner changes to http://127.0.0.1:8000/2ndpage/images/banner.jpg
my polls/header.html template:
<img src="{{ STATIC_URL }}images/gcs_banner.jpg" />
urls.py
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('polls.views',
url(r'^$', 'index'),
url(r'^2ndpage/$', '2ndindex'))
views.py
def index(request):
...
return render_to_response('polls/index.html', {'latest_people_list': latest_people_list,}, context_instance = RequestContext(request))
def 2ndpage(request, people_id):
...
return render_to_response('index/detail.html', {'people': p}, context_instance = RequestContext(request))
Why does the URL change from ../static/.. to ../2ndpage/..? How do I fix this so that when I use {% include 'polls/header.html' %} the banner always shows up?
I think that in the second page, {{ STATIC_URL }} is not defined. Thus, src ends up with images/gcs_banner.jpg. Which is a relative url because it's not prefixed with a slash. It is then converted to a absolute path using the current absolute url: /2ndpage/images/gcs_banner.jpg.
{{ STATIC_URL }} is probably set by a context processor - at least that how it works in my projects. Context processors are actually a feature from RequestContext. When a view returns response without RequestContext then the context processors are not run, e.g.:
from django import shortcuts
# ....
return shortcuts.render_to_response(template_name, context)
This is an example of explicit usage of RequestContext with render_to_response():
from django import shortcuts
from django import template
# ....
return shortcuts.render_to_response(template_name, context,
context_instance=template.RequestContext(request))
That said, Django 1.3 provides a better shortcut with implicit usage of RequestContext, render():
from django import shortcuts
# ....
return shortcuts.render(request, template_name, context)

Categories

Resources