Vue JS widgets in hybrid application - django

I have a hybrid Django/VueJS application. I combine Django templating pages with VueJS widgets because that allows to take best of the 2 different worlds. However, I face an issue when I need to place multiple VueJS widgets. When I need to embed only 1 widget, I just use to embed it. But when I have multiple widgets, I don't know what to do.
Do I need to mount multiple widget separately? Is this a good practice?
Here's how my main.js looks like:
import Vue from "vue";
import vuetify from "./plugins/vuetify";
import router from "./router";
import AccountApp from "./AccountApp.vue";
import store from "./store/index.js";
import i18n from "./i18n";
Vue.config.productionTip = false;
const accountApp = new Vue({
vuetify,
router,
store,
i18n,
render: (h) => h(AccountApp),
});
accountApp.$mount("#app");
Could this be a possible solution?
import Vue from "vue";
import vuetify from "./plugins/vuetify";
import router from "./router";
import AccountApp from "./AccountApp.vue";
import UserApp from "./UserApp.vue";
import store from "./store/index.js";
import i18n from "./i18n";
Vue.config.productionTip = false;
const accountApp = new Vue({
vuetify,
router,
store,
i18n,
render: (h) => h(AccountApp),
});
accountApp.$mount("#account");
const userApp = new Vue({
vuetify,
router,
store,
i18n,
render: (h) => h(UserApp),
});
userApp.$mount("#user");

Related

Ember add customEvents

I'm using Ember 2.9 and would like to use the "paste" event.
How I can add paste as an customEvent on start up the application:
This is my current app.js:
import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
let App;
Ember.MODEL_FACTORY_INJECTIONS = true;
App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver
});
loadInitializers(App, config.modulePrefix);
export default App;
I've setup a demo Ember.js 2.9 app at https://github.com/bartocc/stackoverflow-2176861 that demonstrates the code below.
Here's is an example app.js to configure the Ember.js to listen to the paste event:
// /app/app.js
import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
let App;
Ember.MODEL_FACTORY_INJECTIONS = true;
App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver,
// This is how you make your ember app listen the paste event
customEvents: {
paste: 'paste'
}
});
loadInitializers(App, config.modulePrefix);
export default App;
Find more information in the Ember.js 2.9 API.
Then, make any component listen to the paste event with:
import Ember from 'ember';
export default Ember.Component.extend({
paste(event) {
const text = event.originalEvent.clipboardData.getData('Text');
alert(`you've just pasted the text '${text}'`);
}
});

How to access a Django method from Angular 7

Im pretty new to full stack development so this might actually be an easy question:
I want to be able to access a simple method in the models.py file of my Django backend:
def testMethodFromModelPY(request, path=''):
data = {'returnedData': 'whatever'}
return data
I add the path to the method in urls.py:
from django.urls import path
from DjangoBackEnd import models
urlpatterns = [
# some other paths here that frontend is able to access #
path(r'api/v1/', models.testMethodFromModelPY, name='testMethodFromModelPY'),
]
Now, within Angular frontend I create a component called config in the app folder and add to config.service.ts
export interface Test {
returnedData: string;
}
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
testMethodInConfigServiceTS() {
return this.http.get('/api/v1/testMethodFromModelPY/');
}
}
I include this Service in app.module.ts and call the testMethodInConfigServiceTS function in config.component.ts:
testMethodInConfigComponentTS() {
this.configService.testMethodInConfigServiceTS()
.subscribe(
(data: Test) => this.test = { ...data }, // success path
error => this.error = error // error path
);
}
Within config.component.html I try to access this method with:
<button (click)="testMethodInConfigComponentTS()">teststuffhere</button>
But when I clic a button I get the errormessage:
GET http://127.0.0.1:8000/api/v1/testMethodFromModelPY/ 404 (Not Found)
thanks a lot!
So what you're looking for is angular -> url -> view -> model but you seem to be missing the view in your logic.
Let's break it down.
Add a view to your django application. Django views are functions and/or classes that allow you to handle http requests. They're called by your urls. You can read more about them here. For example your view may look something like this:
from django.http import HttpResponse
from DjangoBackEnd import models
def test_view(request):
output = models.testMethodFromModelPY()
return HttpResponse(output)
Map your views in your urls file.
from django.urls import path
from .views import test_view
urlpatterns = [
# some other paths here that frontend is able to access #
path(r'api/v1/', test_view, name='testMethodFromModelPY'),
]
This will now allow you to hit example-domain.com/api/v1/ which should provide you with the output of your test function in your models. Notice that I haven't added the name of the url aka name='testMethodFromModelPY' as this is used as reference in your templates Jinja code and Djangos internals. You can read more about urls here.
Saying that you'll have to amend your endpoint from:
testMethodInConfigServiceTS() {
return this.http.get('/api/v1/testMethodFromModelPY/');
}
to
testMethodInConfigServiceTS() {
return this.http.get('/api/v1/');
}
Take a look at djangorestframework which is a great toolbox for api driven applications with a django backend.
Good luck!
Make an API and send some requests with angular
Django Rest Framework is easy and fast to set up
https://www.django-rest-framework.org/

Vue.js with Flask server ... Entering url directly into browser does not use vue.js for rendering.

I have vue.js client code with flask server backend code. If I click on various links in my browser app, the links get (using axios) data from backend and render the data properly e.g, if I have a router-link to http://localhost:5000/books. But if I enter this same url directly in the browsers address bar, I get back the raw json from server (i.e, it does not go via vue.js to render in my html table). I am using mode: "history" in my router.js file.
I have browsed other related queries on SO, but still unable to grasp what exactly I need to do to make this work (they all seem to recommend using history mode, which I am. In other cases, they say I need to configure flask to handle such requests .. but do not clearly say what I need to do to handle such requests). Any one have clear idea about this ?
Router.js File
==============================
export default new Router({
routes: [
{ path: "/", name: "home", component: Home },
{ path: "/about", name: "about", component: About },
{ path: "/ping", name: "Ping", component: Ping },
{ path: "/books", name: "Books", component: Books },
{ path: "/*", name: "NotFound", component: NotFound } /*Catch All*/
],
mode: "history"
});
Below is excerpt from my flask app.
Flask App.py
============
from flask import Flask, jsonify, request, send_from_directory, render_template
from flask_cors import CORS
# instantiate the app
app = Flask(__name__, static_url_path='', static_folder='static')
app.config.from_object(__name__)
CORS(app)
...
...
#app.route('/books', methods=['GET'])
def GetAllBooks():
...
...
#app.route('/')
#app.route('/index.html')
def index():
return app.send_static_file('index.html')
#app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
if __name__ == '__main__':
app.run()
Below is my table rendered when I click on "Books" link.
Below is the data returned if I enter the url directly in the address bar.
In my case i use this. For more check this
from flask import Flask, render_template, abort
from jinja2 import TemplateNotFound
app = Flask(__name__, static_folder="./static", template_folder="./templates")
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def index(path):
try:
return render_template('index.html')
except TemplateNotFound:
abort(404)
if __name__ == '__main__':
app.run(debug=True)
Now URL localhost:5000/about will be redirected to index.html and vue-router will handle it within itself.
I've encountered the same issue and solved it with Flask catch-all rules. Flask will catch the url /books and then pass it to Vue application. Since you have activated mode: "history" in Vue, The component Books will be rendered .
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>') # url /books will fail into here
def index(page):
return app.send_static_file('index.html')
#app.route('/static/<path:path>')
def static_file(path):
return app.send_static_file(path)

How to separate flask routes to another modules

I have hundreds of routes in my flask main module,
I think it need to separate those hundred of routes from the main module.
How to do it ?
#!/usr/bin/env python3
# -*- coding: utf8 -*-
from flask import request, url_for
from flask import Flask, request, jsonify
from flask_request_params import bind_request_params
from flask import g
import datetime
import pandas as pd
import pymongo
from webargs import Arg
from webargs.flaskparser import use_args, use_kwargs
import yaml
import time, functools
from pdb import set_trace
from pandas_helper import PandasHelper
import errors
from app_helper import *
from release_schedule import ReleaseSchedule
from mongo import Mongo
#app.route('/next_release', methods=["GET"])
#return_json
def next_release():
schedules = ReleaseSchedule.next_release(DB)
return pd.DataFrame([sche for sche in schedules])
...
#app.route('/last_release', methods=["GET"])
This is what blueprints were made to do.
Another alternative is flask-classy (which is awesome). I'm going to talk about the blueprint approach since that's what I know better.
If I was in your position I would want to split my routes up based on common imports.
Without knowning your application I'm going to guess that a distribution like this
parse_user_data_views.py
from webargs import Arg
from webargs.flaskparser import use_args, use_kwargs
import yaml
push_to_db_views.py
from pandas_helper import PandasHelper
from mongo import Mongo
import pymongo
import pandas as pd
import datetime
release_views.py
from release_schedule import ReleaseSchedule
import pandas as pd
#app.route('/next_release', methods=["GET"])
#return_json
def next_release():
schedules = ReleaseSchedule.next_release(DB)
return pd.DataFrame([sche for sche in schedules])
is likely distribution. We can't answer this for you, only you can.
But this allows you to separate out your application in some pretty nice ways.
in __init__.py
from flask import Flask
from yourapplication.release_views import release_views
from yourapplication.push_to_db_views import push_to_db_views
from yourapplication.parse_user_data_views import parse_user_data_views
app = Flask(__name__)
app.register_blueprint(release_views)
app.register_blueprint(push_to_db_views)
app.register_blueprint(parse_user_data_views)
Create a new file called views.py and add all your routes there. Then import views.py in your __ init __.py .

How can I use DS.RESTAdapter with ember cli?

I created model in models/application.js:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
And created adapter in adapters/application.js:
import Ember from "ember";
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: 'http://site.work/rest/v1/'
});
Route in routes/application.js:
import Ember from 'ember';
export default Ember.Route.extend({
model: function () {
return this.store.all('application');
});
Template in templates/application.hbs
{{#each item in model}}
<li>{{item.name}}</li>
{{/each}}
app.js
import Ember from 'ember';
import Resolver from 'ember/resolver';
import loadInitializers from 'ember/load-initializers';
Ember.MODEL_FACTORY_INJECTIONS = true;
var App = Ember.Application.extend({
modulePrefix: 'chat', // TODO: loaded via config
Resolver: Resolver
});
loadInitializers(App, 'chat');
export default App;
router.js
import Ember from 'ember';
var Router = Ember.Router.extend({
location: ChatENV.locationType
});
Router.map(function() {
this.route("application");
});
export default Router;
JSON example from the server: {"application":[{"id":"1","name":"qwe"},{"id":"2","name":"qwe2"}]}
But my model is empty and I can't find any xhr requests in developer tool.
How should I use DS.RESTAdapter in Ember Cli?
Note: When I add this line into router it's works:
this.store.push('application',{'id':5, 'name':'Is this a question?'});
I'm not sure if the name of your model (application) is causing weird behaviour, since ember(-cli) also uses this name as root for things such as adapter, route, etc.
Apart from that, I would define my adapter as follows:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
namespace: 'rest/v1'
});
and then start your server with:
ember server --proxy=http://site.work