django

2016-10-24 3 views
13

के साथ वू का उपयोग करके मैंने हाल ही में Django का उपयोग करके कुछ सोशल मीडिया वेबसाइट पर शुरुआत की है। मैं अपने पृष्ठों को भरने के लिए डिफ़ॉल्ट django टेम्पलेट इंजन का उपयोग कर रहा हूं। लेकिन इस समय, मैं साइट को और अधिक गतिशील बनाने के लिए जावास्क्रिप्ट जोड़ना चाहता हूं। इसका मतलब यह है:django

  • शीर्ष लेख और पाद प्रत्येक पृष्ठ पर ही है। हेडर में ड्रॉपडाउन मेनू होना चाहिए, एक खोज फ़ॉर्म जो आपके द्वारा टाइप किए जाने पर खोज करता है।
  • मेरे वर्तमान django एप्लिकेशन में आधार टेम्पलेट है जिसमें शीर्षलेख और पाद लेख HTML है, क्योंकि प्रत्येक पृष्ठ में यह होना चाहिए।
  • साइट में एकाधिक पृष्ठ, इंडेक्स पेज, प्रोफाइल पेज, रजिस्टर पेज के बारे में सोचें। इनमें से प्रत्येक पृष्ठ में कुछ आम है लेकिन कई गतिशील घटक भी हैं। उदाहरण के लिए रजिस्टर पेज में फ्लाई पर फॉर्म सत्यापन होना चाहिए, लेकिन प्रोफाइल पेज को इसकी आवश्यकता नहीं है। प्रोफाइल पेज में अनंत स्क्रॉलिंग के साथ एक स्टेटस फीड होना चाहिए।

मैं गतिशील घटकों से निपटने के लिए वू का उपयोग करना चाहता हूं, लेकिन मुझे नहीं पता कि मुझे कैसे शुरू करना चाहिए। आवेदन एसपीए नहीं होना चाहिए।

  • कैसे करना चाहिए मैं संरचना Vue कोड?
  • मुझे बंडल कैसे करना चाहिए। Gulp का उपयोग करना? या शायद django-webpack-loader?
  • मुझे अभी भी Django टेम्पलेट टैग का उपयोग करने में सक्षम होना चाहिए, उदाहरण के लिए मैं ड्रॉपडाउन मेनू में {% url 'index' %} का उपयोग करने में सक्षम होना चाहता हूं।

उत्तर

17

यह राय पर आधारित प्रश्न है जिसके लिए कोई स्पष्ट उत्तर नहीं है।

आपने कहा है कि आप नहीं अनुप्रयोग एक एकल पृष्ठ आवेदन (SPA) होना चाहता हूँ। यदि हां, तो वू का उपयोग करने के लिए प्रेरणा क्या है? पृष्ठ के भीतर उपयोगकर्ता इंटरैक्शन को संभालने के लिए?

वू गैर-एसपीए संदर्भ में पूरी तरह से ठीक काम कर सकता है। यह पृष्ठ के भीतर समृद्ध बातचीत को संभालने में आपकी सहायता करेगा, जैसे ड्रॉप-डाउन, फॉर्म इत्यादि के लिए आपके डेटा को बाध्य करना, लेकिन जब आप इसे एसपीए संदर्भ में उपयोग करते हैं तो वू की वास्तविक शक्ति बाहर आती है।

अपने मामले के लिए, मैं स्टैंडअलोन मोड, जहाँ आप शीघ्रता से आसानी से एक जावास्क्रिप्ट फ़ाइल में Vue घटकों के भीतर template को परिभाषित करने और अपने सभी कोड लिख सकते हैं में Vue.js का उपयोग कर की सिफारिश करेंगे। https://vuejs.org/guide/installation.html#Standalone

"Vue.js स्टैंडअलोन मोड" में, किसी भी webpack निर्माण प्रणाली या vue-cli के लिए कोई जरूरत नहीं है:

यहाँ आप क्या जरूरत है। आप सीधे अपने मौजूदा देव पर्यावरण में डीजेंगो के लिए ऐप बना सकते हैं। gulp वैकल्पिक रूप से आपके जावास्क्रिप्ट फ़ाइलों को सामान्य रूप से छोटा और बंडल कर सकता है, जैसे आप अपने jQuery आधारित ऐप्स के साथ करते हैं।

Vue.js टेम्पलेट्स के लिए डबल घुंघराले ब्रेसिज़ {{..}} का उपयोग करता है, इसलिए यह आपके django टेम्पलेट स्ट्रिंग में हस्तक्षेप नहीं करेगा।

Vue.js के लिए सभी जेएसफ़िल उदाहरण स्टैंडअलोन मोड में चलाएं। यही वही है जो आपको इस पल में चाहिए। आप vue.js टैग के साथ हाल के कुछ प्रश्नों को देख सकते हैं, नमूना jsFiddle ढूंढें और देखें कि यह कैसे किया जाता है।

जटिल एसपीए ऐप्स के लिए, आपको सर्वर के पक्ष से अलग से अपने वू कोड को बनाने की ज़रूरत है, इसे डमी AJAX कॉल के साथ पूरी तरह से जांचें, इसे उत्पादन के लिए बनाएं और फिर अंतिम उत्पादन को अंत तक परीक्षण के लिए अपने सर्वर में बनाएं । यह कुछ ऐसा है जो आप भविष्य में कर सकते हैं।

+1

उल्लेख करना भूल गए - आपका हेडर और पाद लेख वू घटक होगा, जिसमें लेआउट और मार्कअप को परिभाषित करने वाले टेम्पलेट्स होंगे। याद रखें: सभी प्रतिपादन क्लाइंट साइड पर हैं, इसलिए पेज इंडेक्सिंग के लिए Google खोज रोबोट के लिए अनिवार्य रूप से अदृश्य होगा। – Mani

13

मैंने ओपी पूछ रहा था कि काफी कुछ करने के लिए कुछ समय पहले इस सवाल और दूसरों को देखा। दुर्भाग्यवश, वू पर अधिकांश जानकारी एक एसपीए संदर्भ में दी गई है। हालांकि, जैसा कि इवान आपने अक्सर दोहराया है, वू की राय नहीं है और एसपीए के भीतर उपयोग की आवश्यकता नहीं है।

मैं अपने कुछ निष्कर्षों को साझा करना चाहता हूं और Django और Vue को एक साथ काम करने के लिए एक संभावित दृष्टिकोण को स्केच करना चाहता हूं। जबकि एक एसपीए की आवश्यकता नहीं है मुझे लगता है कि वू की वास्तविक शक्ति इसके घटकों से आती है और उस तरह से आपको वेबपैक या इसी तरह के दृष्टिकोण की ओर धक्का देता है, एचटीएमएल में सरल स्टैंडअलोन मोड नहीं है।

इसके अलावा, बस स्पष्ट होने के लिए: मेरी सामग्री का 9 0% + Django कोड और टेम्पलेट्स पहले जैसा ही बना हुआ था। Django विशेष रूप से परवाह नहीं है कि यह webpack_loader और render_bundle का उपयोग कर रहा है। और भी कम है कि render_bundle Vue के साथ कुछ करने के लिए है। Django template blocks, verbatim टैग और वू slots के बीच, आपको बहुत लचीलापन मिलता है जो आपको अपनी अधिकांश मौजूदा सामग्री को अकेले छोड़ने की अनुमति देता है।

अन्त में, Django-webpack की मेरी समझ है कि, जब आप तैयार हैं, आप कर सकते हैं collectstatic और अपने सभी webpack-उत्पन्न बंडलों तो किसी भी नोड के बिना, Django/nginx/अपाचे, अन्य निश्चित संसाधनों की तरह से परोसा जा सकता है या webpack। इस तरह आप जटिल उत्पादन जेएस को अपने उत्पादन प्रणालियों में नहीं जोड़ रहे हैं। :

क्षमा याचना, यह काफी अधूरा है, के रूप में मैं इतना बाहर अलग करना रहा हूँ काम कर कोड की उम्मीद नहीं है (ध्यान दें यह पिछले एक धारणा है, इस बात की पुष्टि या टिप्पणी में खंडन करता है, तो आप जानते हैं कि कृपया है)। लेकिन उम्मीद है कि यह आपको एक विचार देगा।

mysite/__ full12_vue.html:

यह मेरा आधार Vue-ify Django टेम्पलेट है कि मेरे मौजूदा Django आधार टेम्पलेट फैली हुई है, __full12.html है।

  • मान लेते हैं कि __full12.html सभी सामान्य Django ब्लॉक, को परिभाषित करता है की तरह {% ब्लॉक सामग्री%} और तरह

    (वास्तव में, वहाँ ID bme-vue साथ एक बहुत ही महत्वपूर्ण div है मैं इतना हमने इस टेम्पलेट को अंत में भी जोड़ा है।)

  • मैंने उपयोगकर्ता संदेशों को प्रदर्शित करने के लिए एक व्यू घटक जोड़ा है।

  • और वू + बूटस्ट्रैप ड्रॉपडाउन का उपयोग करने के लिए मेनू टेम्पलेट को फिर से परिभाषित किया गया।

{% extends "mysite/__full12.html" %} 
<!-- KEY: use this to hook up to https://github.com/ezhome/django-webpack-loader --> 
{% load render_bundle from webpack_loader %} 


{% block nav %} 
    <!-- uses Vue to setup Bootstrap dropdown menus --> 
    {% include "mysite/menu_vue.html" %} 
{% endblock nav %} 


{% block user_msg %} 
<div class="row"> 
    <div class="col-6"> 
     <!-- uses Vue to display user messages --> 
     <bme-user-messages> 
      <div>THIS SHOULDNT APPEAR ON SCREEN IF VUE WORKED</div> 
     </bme-user-messages> 
    </div> 
</div> 
{% endblock user_msg %} 



{%block extra_js_body_end%} 
    <!-- KEY this points Django Webpack loader to appropriate Webpack entry point --> 
    {% render_bundle bundle_name %} 
{%endblock extra_js_body_end%} 

webpack.config.development.js:

यह वह जगह है जहाँ आप Webpack जो जे एस BUNDLE_NAME आप ध्यान में रखते हुए यह निर्दिष्ट करने के लिए सेवा करने के लिए बताओ।

वेबपैक को कॉन्फ़िगर कैसे करें मेरी पोस्ट के दायरे से बाहर है, लेकिन मैं आपको आश्वस्त कर सकता हूं कि यह वास्तविक पीआईए था। मैंने पाइप django-webpack-loader, फिर https://github.com/NdagiStanley/vue-django के बाद बूटस्ट्रैप 4 सामान के साथ शुरू किया। हालांकि, अंतिम परिणाम स्टैंडअलोन की तुलना में अधिक शक्तिशाली है, मेरी राय में।

/* 
webpack config dev for retest 
*/ 

config.entry = { 
    "main" : [ 
    'webpack-dev-server/client?http://localhost:3000','../../static_src/js/index'], 

    // ....stuff.. 
    //KEY: ONE entrypoint for EACH bundlename that you use. 
    "mydjangoappname/some_django_view" : ["../../static_src/js/mydjangoappname/some_django_view"], 
    "mydjangoappname/another_django_view" : ["../../static_src/js/mydjangoappname/another_django_view"], 
    // ....stuff.. 

} 

    // ....stuff left out... 

mydjangoappname/some_django_template.html

अंत में, हम कुछ वास्तविक सामग्री प्रदर्शित करने के लिए तैयार हैं:

bme-nav-item और bme-tab-pane 2 कस्टम व्यू घटकों मैं बूटस्ट्रैप 4 टैब एनएवी और सामग्री के लिए उपयोग कर रहे हैं ।

Django var settings= some-json-object बल्कि पेज-सामान्य की तुलना में उदाहरण के विशेष संवाद करने के लिए, Vue और जे एस के लिए डेटा का उपयोग करता

{% extends "mysite/__full12_vue.html" %} 

<script> 
// KEY: settings is provided by json.dumps(some_settings_dictionary) 
// which your views puts into your RequestContext. 
// this is how Django tells Vue what changes with different data, on the same view 
var settings = {{settings | safe}}; 
</script> 

{% block content %} 

    <!-- a button to run a Celery batch via a post command, url should probably come 
    from Django url reverse and be put into a Vue property... 
    --> 
    <button v-bind:data-url="url_batch" type="button" class="btn btn-block btn-outline-primary" @click.prevent="run_batch"> 

    <!-- lotsa stuff left out.... --> 

    <ul id="tab-contents-nav" class="nav nav-tabs nav-pills"> 

    <!-- *label* is using a Vue Prop and because there is no {% verbatim %} guard around it, Django will 
     inject the contents. {% urlrev xxx %} could be used to write to an 'url' prop. Ditto the conditional 
     inclusion, by Django, of a template if it's in the RequestContext. 
    --> 
     {% if templatename_details %} 
     <bme-nav-item link="details" 
      label="{{details_label}}" >   
     </bme-nav-item> 
     {% endif %} 

<!-- lotsa stuff left out.... --> 

<bme-tab-pane link="details"> 
    <div slot="content"> 

     <!-- KEY: Vue slots are incredibly powerful with Django. Basically this is saying 
        to Django : inject what you want in the slot, using your include, I'll tidy up afterwards. 
        In my case, this is a Bootstrap NavItem + NavTab 
     --> 
     {% if templatename_details %} 

      {% include templatename_details %} 
     {% else %} 
      <span class="text-warning">SHOULDNT APPEAR IF VUE WORKED </span> 
     {% endif %} 

    </div> 
</bme-tab-pane> 

{% endblock content %} 

mydjangoappname/some_django_view.js:

import Vue from 'vue'; 
    import Vuex from 'vuex'; 
    //now Vue is using Vuex, which injects $store centralized state variables as needed 
    Vue.use(Vuex); 



    //KEY: re-using components defined once. 
    import {base_messages, base_components} from '../mysite/commonbase.js'; 

    var local_components = { 
    //nothing, but I could have imported some other components to mix-n-match 
    //in any case, bme-nav-item, bme-tab-pane and bme-user-messages need to 
    //coming from somewhere for this page! 
    }; 

    const components = Object.assign({}, base_components, local_components); 

    //we're going to put together a Vue on the fly... 

    export function dovue(config) { 

     //KEY: The store is a Vuex object - don't be fooled, it's not SPA-only 
     // it's the easiest way to coherently share data across Vue Components, so use it. 
     store.commit('initialize', config); 

     //here I am telling the store which html IDs need hiding 
     var li_tohide = settings.li_tohide || []; 
     li_tohide.forEach(function(hidden) { 
      store.commit('add_hidden', hidden); 
     }); 

     /* eslint-disable no-new */ 
     var vm = new Vue({ 

     //KEY: This tells the Vue instance what parts of your html are in its scope. 
     el: '#bme-vue' 

     //KEY: each bme-xxx and bme-yyy special tag needs to be found in components below 
     //otherwise you'll see my SHOULDNT APPEAR IF VUE WORKED text in your page 
     ,components: components 

     ,data: { 
      li_rowcount: window.settings.li_rowcount || [] 
      ,csrf_token: window.csrf_token 
      ,url_batch: "some url" 
     } 
     ,mounted: function() { 
      // a Vue lifecycle hook. You could use to set up Vue Event listening for example 
      console.log("data.js.lifecycle.mounted"); 
     } 
     ,methods : { 
      ,run_batch: function(e) { 
       //hook this up to a button 
       console.assert(this.$data, COMPONENTNAME + ".run_batch.this.$data missing. check object types"); 
       var url = e.target.dataset.url 

       //this is defined elsewhere 
       post_url_message(this, url, this.csrf_token); 
      } 
     } 
     //the Vuex instance to use for this Vue. 
     ,store: store 
     }); 

     //did Django provide any user messages that need displaying? 
     var li_user_message = config.li_user_message || []; 

     li_user_message.forEach(function(user_message, i) { 
     //the bme-user-messages Component? It's listening for this event 
     //and will display Bootstrap Alerts for them. 
     vm.$emit(base_messages.EV_USER_MESSAGE, user_message); 
     }); 
     return vm; 
    } 

    //various app and page specific settings... 
    import {app_config, LOCALNAV_LINK, TOPNAV_LINK_OTHERS} from "./constants"; 
    var page_config = { 
    //used to show which navigation items are .active 
    localnav_link : LOCALNAV_LINK.data 
    , topnav_link: TOPNAV_LINK_OTHERS.system_edit_currentdb 
    }; 

    //this is coming from Django's RequestContext. 
    var generated_config = window.settings; 

    //ok, now we are merging together a Django app level config, the page config and finally 
    //what the Django view has put into settings. This will be passed to the Vuex store 
    //individual Vue Components will then grab what they need from their $store attribute 
    //which will point to that Vuex instance. 
    var local_config = Object.assign({}, app_config, page_config, generated_config); 
    var vm = dovue(local_config); 

vuex/सामान्य .js:

और एक बेवकूफ, ज्यादातर पढ़ने-योग्य स्टोर ई कार्यान्वयन:

//you can add your page's extra state, but this is a shared baseline 
//for the site 
const state = { 
    active_tab: "" 
    ,topnav_link: "" 
    ,localnav_link: "" 
    ,li_user_message: [] 
    ,s_visible_tabid: new Set() 
    ,urls: {} 
}; 
const mutations = { 
    //this is what your page-specific JS is putting into the state. 
    initialize(state, config){ 
     //initialize the store to a given configuration 
     //KEY: attributes that did not exist on the state in the first place wont be reactive. 
     // console.log("store.initialize"); 
     Object.assign(state, config); 
    }, 
    //a sample mutation 
    set_active_tab(state, tabid){ 
     //which bme-tab-nav is active? 
     if (! state.s_visible_tab.has(tabid)){ 
      return; 
     } 
     state.active_tab = tabid; 
    }, 
}; 

export {state as generic_state, mutations}; 

और आप सामान्य फ़ाइल पदानुक्रम की एक विचार देने के लिए:

. 
./manage.py 
./package.json //keep this under version control 
./ 

├── mydjangoappname 
│   ├── migrations 
│   └── static 
│    └── mydjangoappname 
├── node_modules 
├  //lots of JavaScript packages here, deposited/managed via npm && package.json 
├── static 
│   └── js 
├── static_src 
│   ├── assets 
│   ├── bundles 
│   │   // this is where django-webpack-loader's default config deposits generated bundles... 
│   │   // probably belonged somewhere else than under static_src ... 
│   │   ├── mydjangoappname 
│   ├── components 
│   │   ├── mydjangoappname 
│   ├── css 
│   ├── js 
│   │   ├── mydjangoappname 
│   │   └── mysite 
│   └── vuex 
│    ├── mydjangoappname 
├── staticfiles 
│   // for Production, collectstatic should grab django-webpack-loader's bundles, I think... 
├── templates 
│   ├── admin 
│   │   └── pssystem 
│   ├── mydjangoappname 
│   └── mysite 
└── mysite 
    ├── config 
    ├  // where you configure webpack and the entry points. 
    ├  webpack.config.development.js 
    ├── sql 
    │   └── sysdata 
    ├── static 
    │   └── mysite 
    └── templatetags 

ठीक है, मुझे यकीन है कि div # BME-Vue है बनाने के लिए साइट की मूल टेम्पलेट को संशोधित करने की क्या ज़रूरत थी हमेशा उपलब्ध।

शायद इस और mysite/__ full12_vue.html के बीच आवश्यक कुछ रिफैक्टरिंग की आवश्यकता है।

mysite/__ full12.html:

पहले दृष्टिकोण अलग Django और Vue क्षुधा बनाने जा रहा है:

<!-- lots of stuff left out --> 
<body> 

    <!--  KEY: the #bme-vue wrapper/css selector tells Vue what's in scope. 
    it needs to span as much of the <body> as possible, but 
    also end right BEFORE the render_bundle tag. I set that css 
    selector in mydjangoappname/some_django_view.js and I'd want to 
    use the same selector everywhere throughout my app. 
    --> 

    <div id="bme-vue"> 
     <!-- anything that ends up here 
, including through multiple nested/overridden Django content blocks 
, can be processed by Vue 
, but only when have Vue-relevant markup 
such as custom component tags or v-for directives. 
--> 

    ...more blocks... 
    {% block search %} 
    {% endblock search %} 

    <div id="main" role="main"> 
     <div> <!-- class="container"> --> 
      {% block content %} 
      {% endblock %} 
     </div> 
    </div> 
    ...more blocks... 


    </div> <!-- bme-vue --> 
    {%block extra_js_body_end%} 
    {%endblock extra_js_body_end%} 
</body> 
</html> 
+0

बहुत बढ़िया विवरण, धन्यवाद। वास्तव में उस समय की सराहना करते हैं जब आपने इसे एक साथ रखा था। – chuckjones242

1

इस तरह मैं एक Django परियोजना के साथ Vue एकीकृत है। डीजेगो डीजेगो रीस्ट फ्रेमवर्क का उपयोग करके बनाए गए एपीआई की सेवा के लिए ज़िम्मेदार होगा और वू एक्सिस क्लाइंट या ब्राउज़र के fetch API का उपयोग करके इन एपीआई का उपभोग करेगा। आपको विकास और उत्पादन दोनों में दो सर्वर होना चाहिए, एक Django (REST API) के लिए और दूसरा Vue (स्थिर फ़ाइलों को प्रस्तुत करने के लिए) के लिए।

दूसरा दृष्टिकोण अलग-अलग है और बैकएंड ऐप्स को जोड़ा जाएगा। असल में आप डैंजो का उपयोग वू फ्रंटेंड की सेवा करने और आरईएसटी एपीआई का पर्दाफाश करने के लिए करेंगे।तो अगर आप Django के साथ Vue और Webpack एकीकृत करने के लिए की आवश्यकता होगी, निम्न चरणों का है कि आप उस

सबसे पहले इस परियोजना निर्देशिका के अंदर फिर अपने Django परियोजना पैदा करते हैं Vue CLI

का उपयोग कर अपने Vue आवेदन उत्पन्न करने के लिए अनुसरण कर सकते हैं कर रहे हैं Django परियोजना के लिए पिप के साथ django-webpack-loader स्थापित:

pip install django-webpack-loader 

अगला निम्नलिखित वस्तु

WEBPACK_LOADER = { 
    'DEFAULT': { 
      'BUNDLE_DIR_NAME': '', 
      'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), 
     } 
} 
जोड़कर इंस्टॉल किए गए एप्लिकेशन में ऐप जोड़ने और settings.py में कॉन्फ़िगर

फिर

{ % load render_bundle from webpack_loader % } 

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="UTF-8" /> 
    <meta name="viewport" content="width=device-width" /> 
    <title>Django + Vue</title> 
    </head> 
    <body> 
    <div id="root"> 
    This is where Vue will be mounted 
    </div> 
    { % render_bundle 'app' % } 
    </body> 
</html> 

तो इस टेम्पलेट की सेवा के लिए urls.py में एक URL जोड़ने कि Vue आवेदन माउंट करने के लिए इस्तेमाल किया जाएगा और Django

द्वारा परोसा जाएगा एक Django टेम्पलेट जोड़ने

from django.conf.urls import url 
from django.contrib import admin 
from django.views.generic import TemplateView 

urlpatterns = [ 

    url(r'^', TemplateView.as_view(template_name="main.html")), 

] 

हैं आप इस बिंदु पर Django और Vue सर्वर दोनों को शुरू करते हैं, आपको एक Django त्रुटि मिल जाएगी जो वेबपैक-आँकड़े.जेसन मौजूद नहीं है। तो इसके बाद आपको अपने वू एप्लिकेशन को आंकड़े फ़ाइल जेनरेट करने में सक्षम होना चाहिए।

आगे बढ़ो और अपने Vue ऐप में जाएं, फिर webpack गठरी-ट्रैकर

npm install webpack-bundle-tracker --save 

build/webpack.base.conf.js पर जाएं तो जोड़ने स्थापित

let BundleTracker = require('webpack-bundle-tracker') 
module.exports = { 
    // ... 
    plugins: [ 
    new BundleTracker({filename: '../webpack-stats.json'}), 
    ], 
} 

यह Webpack को BundleTracker प्लगइन जोड़ सकते हैं और यह बताना मूल फ़ोल्डर में webpack-stats.json फ़ाइल जेनरेट करने के लिए जहां Django फ़ाइलें रहते हैं।

अब यदि आप अपने वू सर्वर को फिर से चलाते हैं तो वेबपैक-आँकड़े.जेसन उत्पन्न हो जाएंगे और Django Vue dev सर्वर द्वारा जेनरेट किए गए वेबपैक बंडलों के बारे में जानकारी प्राप्त करने में सक्षम होगा।

आप इस tutorial से अधिक जानकारी प्राप्त कर सकते हैं।