Converting Recursive Dictionary to html element UI and LI

تبدیل دیکشنری به المنت های html برای طراحی چارت سازمانی یا منوهای درختی که بشدت کاربردی هست
حالا در نظر بگیرید ما یک دیکشنری داریم با مشخصات زیر

{name: "a", children:[{name: "b", children: [] },{..},{..}]

حالا برای تبدیل اون از کد زیر استفاده کنیم :

def ConvertDictToUlLi():
    jsonResult = GetSomeRecursiveDict()

    def CreateHtml(DictItem, output):
        output = "<li>"+DictItem["name"] if jsonResult.has_key("name") else " "
        if len(DictItem["children"]) > 0:
           output = output + "<ul>"
           for item in DictItem["children"]:
              output = output + "  "+CreateHtml(item, output)+"  "
           output = output + "</ul>"
      return output+"</li>"
    result = "<ul class='tree'>"+CreateHtml(jsonResult, "")+"</ul>"

return result

موفق باشید

مشکل در درخواست های همزمان در Tornado

Here’s a complete sample Tornado app that uses the Async HTTP client and the gen.Task module to make things simple.If you read more about gen.Task in the docs you’ll see that you can actually dispatch multiple requests at the same time. This is using the core idea of Tornado where everything is no blocking and still maintaining a single process. 

ادامه مطلب

Tornado

Tornado is a Python web framework and asynchronous networking library, originally developed atFriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.

ادامه مطلب

Djangular

یکی از دغدغه های من آوردن AngularJS به Django بوده و این موضوع کاملا با Djangular پوشش داده میشه :)))

مراحل کار :

pip install django-angular
INSTALLED_APPS = (
    ...
    'djangular',
    ...
)

STATIC_ROOT and STATIC_URL فراموش نشود و سپس جرای دستور :

python manage.py collectstatic

دستور بالا مسیر استاتیک را با فایل های مورد نیاز دیجنگولار بروز رسانی میکند یعنی باید مسیر مورد نظر مجوز ویرایش را داشته باشد هاا

البته دیجانگولار هیچ مدل داده ای ندارد و بدون تغییرات بانک اطلاعاتی می تواند عملیات خود را ادامه دهد

 Integrate AngularJS with Django

XMLHttpRequest

معمولا در وب سایت ها درخواست های آژادکسی هدر خود را بصورت زیر ارسال میکنند :

X-Requested-With: XMLHttpRequest

این هدر است که به دیجانگو امکان میدهد تا بفهمد :

request.is_ajax()

حالا برای اینکه این امکان رو فراهم کنیم کافیگ زیر را برای appمون منویسیم

var my_app = angular.module('MyApp').config(function($httpProvider) {
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
});

 Template tags

برای اینکه تگ های آنگولار با تگ های دیجاگو گیژ نزنن کد زیر رو میزنیم :

var my_app = angular.module('MyApp').config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');
});

راستی این رو هم اضافه کنید :

<script src="{% static 'djangular/js/django-angular.min.js' %}" type="text/javascript"></script>

و سپس :

var my_app = angular.module('myApp', [/* other dependencies */, 'ng.django.forms']);

حالا تو لینک زیر یه مثال خوب هست که بهش توجه کنیم :

https://github.com/jrief/django-angular/tree/master/examples

Integrate a Django form with an AngularJS model

هر گاه می خواهیم forms.Form رو ببریم بسمت AngularJS Env برای ما لازم است که به یک صفحه ی رندر شده ی AngularJSی دسترسی پیدا کنیم

ng-model="model_name"

where model_name corresponds to the named field from the declared form class. :)))

کد نمونه :

در نظر بگیریم که یک کلاس فرم ساده دیجانگو داریم که از یک فرم ورود متن ساده تشکیل شده است و ما می خواهیم دهنش رو با آوردن به djangularjs کلاس NgModelFormMixin سرویس کنیم

from django import forms
from django.utils import six
from djangular.forms import NgDeclarativeFieldsMetaclass, NgModelFormMixin

class ContactForm(six.with_metaclass(NgDeclarativeFieldsMetaclass, NgModelFormMixin, forms.Form)):
    subject = forms.CharField()
    # more fields ...

در مثال بالا همونطور که معلومه فرم ما از دیجانگو فرم برگفته شده است و در عوض میشه اینطوری هم نوشتش :

from djangular.forms import NgModelFormMixin, NgForm

class MyValidatedForm(NgModelFormMixin, NgForm):
    # members as above

و همینطور اینگونه :

from djangular.forms import NgModelFormMixin, NgModelForm

class MyValidatedForm(NgModelFormMixin, NgModelForm):
    class Meta:
         model = Article

    # fields as usual

حالا آبجکت های اینطوری رندر میشن :

<input id="id_subject" type="text" name="subject" ng-model="subject" />

حالا یه مثال کامل :

مثال زیر نشان دهنده ی ارسال داده هاست بوسیله ی انگولارجی اس کنترولر. و ویروی دیجانگو که قراره کنترل کننده ی اون باشه به شکل زیره :

from django.views.generic import TemplateView

class ContactFormView(TemplateView):
    template = 'contact.html'

    def get_context_data(self, **kwargs):
        context = super(ContactFormView, self).get_context_data(**kwargs)
        context.update(contact_form=ContactForm())
        return context

و حالا تمپلیت contact.html

<form ng-controller="MyFormCtrl" name="contact_form">
    {{contact_form}}
    <button ng-click="submit()">Submit</button>
</form>

یه کمی هم جاوا اسکریپت قاطیش می کنیم :

my_app.controller('MyFormCtrl', function($scope, $http) {
    $scope.submit = function() {
        var in_data = { subject: $scope.subject };
        $http.post('/url/of/your/contact_form_view', in_data)
            .success(function(out_data) {
                // do something
            });
    }
});

و اما اینکه <form> نیازی به method or action نداره و از طریق success کنترلر ارسال میشه و تمام ابعاد قضیه رو شامل ارسال و پاسخ رو در نظر میگیره مثل ارسال ارورهای اعتبارسنجی شده و …

به طور معمول form view میبایست داده های پست شده رو از طریق POST دریافت کنه در حالی که AngularJS دیتا رو از طریق multipart/form-data or application/x-www-form-urlencoded نمی تونه ارسال کنه البته به خاطر یه سری مسایل دیکودینگ هااا

برای جواب داده به فرم هم بهتره از کد زیر استفاده بشه :

import json
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponseBadRequest

class ContactFormView(TemplateView):
    # use ‘get_context_data()’ from above

    @csrf_exempt
    def dispatch(self, *args, **kwargs):
        return super(ContactFormView, self).dispatch(*args, **kwargs)

    def post(self, request, *args, **kwargs):
        if not request.is_ajax():
            return HttpResponseBadRequest('Expected an XMLHttpRequest')
        in_data = json.loads(request.body)
        bound_contact_form = CheckoutForm(data={'subject': in_data.get('subject')})
        # now validate ‘bound_contact_form’ and use it as in normal Django

در مثال بالا csrf_exempt رو زدیم ها ولی بکار نبریدش کلا یعنی همیشه از امنیتش استفاده کنید

Prefixing the form fields

The problem with this implementation, is that one must remember to access each form field three times. Once in the declaration of the form, once in the Ajax handler of the AngularJS controller, and once in the post handler of the view. This make maintenance hard and is a violation of the DRY principle. Therefore it makes sense to add a prefix to the model names. One possibility would be to add the argument scope_prefix on each form’s instantiation, ie.:

متن بالا رو نمی تونم ترجمه کنم خدتون بخونید بهتره

حالا برای اینکه مشکل متن بالا پیش نیاد بهتره از prefixاستفاده کنیم

class ContactForm(NgModelFormMixin, forms.Form):
    # declare form fields

    def __init__(self, *args, **kwargs):
        kwargs.update(scope_prefix='my_prefix')
        super(ContactForm, self).__init__(*args, **kwargs)

حالا خروجی تو آنگولار به شکل زیر میشه میشه :

<input id="id_subject" type="text" name="subject" ng-model="my_prefix.subject" />

این بالاییه حالا میتونه ارسال آزاکسی رو راحتتر کنه برای اینکه هر ارسال بروی یک آبجکت جاوا اسکریپتی انجام میشه :)) و میشه اون رو بصورت  scope.my_prefix ارسال نمود

$http.post('/url/of/contact_form_view', $scope.my_prefix)

Validate Django forms using AngularJS

NgFormValidationMixin

from django import forms
from django.utils import six
from djangular.forms import NgDeclarativeFieldsMetaclass, NgFormValidationMixin

class MyValidatedForm(six.with_metaclass(NgDeclarativeFieldsMetaclass, NgFormValidationMixin, forms.Form)):
    form_name = 'my_valid_form'
    surname = forms.CharField(label='Surname', min_length=3, max_length=20)
    age = forms.DecimalField(min_value=18, max_value=99)

باز نویسی کنیم به روش ساده تری :

from djangular.forms import NgFormValidationMixin, NgForm

class MyValidatedForm(NgFormValidationMixin, NgForm):
    # members as above
from djangular.forms import NgFormValidationMixin, NgModelForm

class MyValidatedForm(NgFormValidationMixin, NgModelForm):
    class Meta:
         model = Article

    # fields as usual

هر صفحه ای انگولارجی اس نیاز به یک نام منحصربفرد داره در غیر اینصورت اعتبار سنجی ها شاسکول میشن. در نتیجه باید هر فرم از NgFormValidationMixin گرفته بشه

اگر در یک صفحه فقط یک فرم داشته باشیم، نام فرم میتواند در به class declaration مثل مثال پایین اضافه بشه :

تک فرمی :

def get_context_data(self, **kwargs):
    context = super(MyRenderingView, self).get_context_data(**kwargs)
    context.update(form=MyValidatedForm())
    return context

چند فرمی :

def get_context_data(self, **kwargs):
    context = super(MyRenderingView, self).get_context_data(**kwargs)
    context.update(form1=MyValidatedForm(form_name='my_valid_form1'),
                   form2=MyValidatedForm(form_name='my_valid_form2'))
    return context

 Render this form in a template

<form name="{{ form.form_name }}" novalidate>
  {{ form }}
  <input type="submit" value="Submit" />
</form>

Use the directive novalidate to disable the browser’s native form validation

این هم برای دکمه ی سابمیت :

<input type="submit" class="btn" ng-disabled="{{ form.form_name }}.$invalid" value="Submit">

 More granular output

from django import forms
from djangular.forms import NgFormValidationMixin

class MyValidatedForm(NgFormValidationMixin, forms.Form):
    email = forms.EmailField(label='Email')
<ul class="djng-form-errors" ng-hide="subscribe_form.email.$pristine">
  <li ng-show="subscribe_form.email.$error.required" class="ng-hide">This field is required.</li>
  <li ng-show="subscribe_form.email.$error.email" class="">Enter a valid email address.</li>
</ul>

 Combine NgFormValidationMixin with NgModelFormMixin

from django import forms
from djangular.forms import NgFormValidationMixin, NgModelFormMixin

class MyValidatedForm(NgModelFormMixin, NgFormValidationMixin, forms.Form):
    # custom form fields

but don’t do this

class MyValidatedForm(NgFormValidationMixin, NgModelFormMixin, forms.Form):
    # custom form fields

and this :

form = MyValidatedForm(form_name='my_form', scope_prefix='my_model')

css class for errors :

ul.djng-form-errors {
        margin-left: 0;
        display: inline-block;
        list-style-type: none;
}
ul.djng-form-errors li.invalid {
        color: #e9322d;
}
ul.djng-form-errors li.invalid:before {
        content: "\2716\20";  /* adds a red cross before the error message */
}
ul.djng-form-errors li.valid:before {
        color: #00c900;
        content: "\2714";  /* adds a green tick */
}

If you desire an alternative CSS class or an alternative way of rendering the list of errors, then initialize the form instance with

class MyErrorList(list):
    # rendering methods go here

# during form instantiation
my_form = MyForm(error_class=MyErrorList)

توجه کنید و مثال های دیگر

from django import forms

class MyForm(forms.Form):
    # other fields
    date = forms.DateField(label='Date',
        widget=forms.widgets.DateInput(attrs={'validate-date': '^(\d{4})-(\d{1,2})-(\d{1,2})$'}))
<input name="date" ng-model="my_form_data.birth_date" type="text" validate-date="^(\d{4})-(\d{1,2})-(\d{1,2})$" />
angular.module('MyApp', ['ng.django.forms']);

Django REST framework

django REST framework logoDjango REST framework یک فریم ورک قدرتمند و انعطاف پذیر است که طراحی سرور ساید و تا قسمتی کلاینت ساید یک وب پرتال پیچیده را ساده می نماید.تعدادی از دلایلی که شما را مجاب می کند تا از این فریم ورک استفاده نمایید بشرح زیر است :* API های این فریم ورک توسط مرورگر شما قابل استفاده است و نیازی به کد زدن شما ندارد !!* سیستم های کنترل دسترسی شامل پکیج های OAuth1a and OAuth2* سریال سازی شامل ORM and non-ORM data sources* بهینه سازی تمام مسیرهای طراحان دیجانگو در جهت مختصر نویسی و استحکام* مستند سازی قدرتمند و کامل* استفاده توسط تعداد زیادی از شرکت های بزرگ مثل Mozzila and Eventbrite 

نحوه ی نصب :

Requirements

REST framework requires the following:

  • Python (2.6.5+, 2.7, 3.2, 3.3, 3.4)
  • Django (1.4.11+, 1.5.6+, 1.6.3+, 1.7+, 1.8)

The following packages are optional:

Installation

Install using pip, including any optional packages you want…

pip install djangorestframework
pip install markdown       # Markdown support for the browsable API.
pip install django-filter  # Filtering support

…or clone the project from github.

git clone git@github.com:tomchristie/django-rest-framework.git

Add 'rest_framework' to your INSTALLED_APPS setting.

INSTALLED_APPS = (
    ...
    'rest_framework',
)

If you’re intending to use the browsable API you’ll probably also want to add REST framework’s login and logout views. Add the following to your root urls.py file.

urlpatterns = [
    ...
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

خوب با نحوه ی نصب این فریم ورک آشنا شدیمهمانطور که مشاهده می کنید این فریم ورک جایگزین خوبی را برای صفحه مدیریت جانگو ایجاد میکنه. یعنی اگر قبلا از rahsoon.com:8000/admin استفاده میشد برای ایجاد کاربری جدید حالا این فریم ورک از همین آدرس و با استفاده از روش دیگری برای ساختن کاربری جدید جایگزین می نمایدمثالی مختصری از نحوه ی استفاده این فریم ورک را اشاره می کنمدر نظر داشته باشید می خواهیم 
TopTal

Django User Authentication

در رست فریم ورک دی جانگو Authentication معمولا قبل از هر request اجرا میشه و همچنین قبل از اجرا شدن هر کدیاین کنترل هویت در دو مدل در رست کنترل میشه :request.user property  : این خصیصه به یک instance از پکیج contrib.auth در کلاس User اختصاص داده میشهrequest.auth property : این خصیصه نیز برای فعالیت های اضافی در کنترل های صحت عمکلردها بکار بسته میشود بعنوان مثال این خصیصه می تواند نشان دهنده ی یک رشته فعالیت هایی باشد که طراح مشخص کرده آیا کاربرش انجام داده یا خیرخوب چگونه صحت سنجی کاربر کار می کندAuthentication Schema معمولا بصورت لیستی از کلاس ها قرار میگیرد. رست شروع می کند و به ترتیب صحت سنجی را با کلاس های لیست شده انجام می دهد و سپس request.auth and request.user  را برای اولین کلاسی که به درستی صحت سنجی شده باشد را بر میگرداند.اگر صحت سنجی کلاسی صورت نپذیرد بجای آن دو خصیصه یک کلاس بنام django.contrib.auth.models.AnonymousUser برای request.user برگشت داده شده و همچنین None به request.auth اختصاص داده میشود. ضمنا می توان این وضعیت را UNAUTHENTICATED_USER and UNAUTHENTICATED_TOKEN در settings.py مدیریت نمود.مواردی که باید تحقیق شود : فرق بین router and url در django rest framework : در اصل این روتر ها یکی از امکانات viewSet ها هستند که بر میگردد به مدلی که برنامه نویس برای توسعه ی نرم افزار خود در پیش گرفته است.زمانی که از viewset بجای view‌استفاده می نماییم می توانیم بصورت خودکار از ui درخواست ها را گرفته و با کمترین شلوغی در کد با یک روتر کلاس در ویو ست آنها را اجرا کرده و نتیجه را منعکس نماییم. در نتیجه با استفاده از این روتر کلاس ها می توانیم در restframework admin نیز این مسیر ها را مشاهده و دستکاری نماییمحالا برای اینکه از دیجانگو به درک بهتری برسم دارم این آدرس رو پیاده سازی و تست میکنم :‌خوب مثال یک لینک اشاره رو ردیف کردم :چیزی که تو این مثال اورده بود بیشتر شبیه به همون متدهای قبلی جانگو فرم بود و فقط بجای مثلا فرم یه سریالایزر از نوع مدل گذاشتمحالا میرم تو مثال دوم 

farsiTutorial 2: Requests and ResponsesFrom this point we’re going to really start covering the core of REST framework. Let’s introduce a couple of essential building blocks.Request objectsREST framework introduces a Request object that extends the regular HttpRequest, and provides more flexible request parsing. The core functionality of the Request object is the request.data attribute, which is similar to request.POST, but more useful for working with Web APIs.request.POST # Only handles form data. Only works for 'POST' method. request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods. 
farsiResponse objectsREST framework also introduces a Response object, which is a type of TemplateResponse that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.return Response(data) # Renders to content type as requested by the client.
farsitatus codesUsing numeric HTTP status codes in your views doesn’t always make for obvious reading, and it’s easy to not notice if you get an error code wrong. REST framework provides more explicit identifiers for each status code, such as HTTP_400_BAD_REQUEST in thestatus module. It’s a good idea to use these throughout rather than using numeric identifiers.
farsiWrapping API viewsREST framework provides two wrappers you can use to write API views.The @api_view decorator for working with function based views.The APIView class for working with class based views.These wrappers provide a few bits of functionality such as making sure you receive Request instances in your view, and adding context to Response objects so that content negotiation can be performed.The wrappers also provide behaviour such as returning 405 Method Not Allowed responses when appropriate, and handling anyParseError exception that occurs when accessing request.data with malformed input.
farsiPulling it all togetherOkay, let’s go ahead and start using these new components to write a few views.We don’t need our JSONResponse class in views.py anymore, so go ahead and delete that. Once that’s done we can start refactoring our views slightly.from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from snippets.models import Snippet from snippets.serializers import SnippetSerializer @api_view(['GET', 'POST']) def snippet_list(request): """ List all snippets, or create a new snippet. """ if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)Our instance view is an improvement over the previous example. It’s a little more concise, and the code now feels very similar to if we were working with the Forms API. We’re also using named status codes, which makes the response meanings more obvious.Here is the view for an individual snippet, in the views.py module.@api_view(['GET', 'PUT', 'DELETE']) def snippet_detail(request, pk): """ Retrieve, update or delete a snippet instance. """ try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = SnippetSerializer(snippet) return Response(serializer.data) elif request.method == 'PUT': serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)This should all feel very familiar – it is not a lot different from working with regular Django views.Notice that we’re no longer explicitly tying our requests or responses to a given content type. request.data can handle incomingjson requests, but it can also handle other formats. Similarly we’re returning response objects with data, but allowing REST framework to render the response into the correct content type for us.
farsiAdding optional format suffixes to our URLsTo take advantage of the fact that our responses are no longer hardwired to a single content type let’s add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such as http://example.com/api/items/4/.json.Start by adding a format keyword argument to both of the views, like so.def snippet_list(request, format=None):anddef snippet_detail(request, pk, format=None):Now update the urls.py file slightly, to append a set of format_suffix_patterns in addition to the existing URLs.from django.conf.urls import patterns, url from rest_framework.urlpatterns import format_suffix_patterns from snippets import views urlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail), ] urlpatterns = format_suffix_patterns(urlpatterns)We don’t necessarily need to add these extra url patterns in, but it gives us a simple, clean way of referring to a specific format.How’s it looking?Go ahead and test the API from the command line, as we did in tutorial part 1. Everything is working pretty similarly, although we’ve got some nicer error handling if we send invalid requests.We can get a list of all of the snippets, as before.http http://127.0.0.1:8000/snippets/ HTTP/1.1 200 OK ... [ { "id": 1, "title": "", "code": "foo = \"bar\"\n", "linenos": false, "language": "python", "style": "friendly" }, { "id": 2, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly" } ]We can control the format of the response that we get back, either by using the Accept header:http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTMLOr by appending a format suffix:http http://127.0.0.1:8000/snippets/.json # JSON suffix http http://127.0.0.1:8000/snippets/.api # Browsable API suffixSimilarly, we can control the format of the request that we send, using the Content-Type header.# POST using form data http --form POST http://127.0.0.1:8000/snippets/ code="print 123" { "id": 3, "title": "", "code": "print 123", "linenos": false, "language": "python", "style": "friendly" } # POST using JSON http --json POST http://127.0.0.1:8000/snippets/ code="print 456" { "id": 4, "title": "", "code": "print 456", "linenos": false, "language": "python", "style": "friendly" }Now go and open the API in a web browser, by visiting http://127.0.0.1:8000/snippets/.BrowsabilityBecause the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. This allows for the API to return a fully web-browsable HTML representation.Having a web-browsable API is a huge usability win, and makes developing and using your API much easier. It also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API.See the browsable api topic for more information about the browsable API feature and how to customize it.What’s next?In tutorial part 3, we’ll start using class based views, and see how generic views reduce the amount of code we need to write. 
farsiTutorial 3: Class Based ViewsWe can also write our API views using class based views, rather than function based views. As we’ll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code DRY.
farsiRewriting our API using class based viewsWe’ll start by rewriting the root view as a class based view. All this involves is a little bit of refactoring of views.py.from snippets.models import Snippet from snippets.serializers import SnippetSerializer from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class SnippetList(APIView): """ List all snippets, or create a new snippet. """ def get(self, request, format=None): snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)So far, so good. It looks pretty similar to the previous case, but we’ve got better separation between the different HTTP methods. We’ll also need to update the instance view in views.py.class SnippetDetail(APIView): """ Retrieve, update or delete a snippet instance. """ def get_object(self, pk): try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 def get(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet) return Response(serializer.data) def put(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): snippet = self.get_object(pk) snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)That’s looking good. Again, it’s still pretty similar to the function based view right now.We’ll also need to refactor our urls.py slightly now we’re using class based views.from django.conf.urls import url from rest_framework.urlpatterns import format_suffix_patterns from snippets import views urlpatterns = [ url(r'^snippets/$', views.SnippetList.as_view()), url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()), ] urlpatterns = format_suffix_patterns(urlpatterns)Okay, we’re done. If you run the development server everything should be working just as before.
farsiUsing mixinsOne of the big wins of using class based views is that it allows us to easily compose reusable bits of behaviour.The create/retrieve/update/delete operations that we’ve been using so far are going to be pretty similar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework’s mixin classes.Let’s take a look at how we can compose the views by using the mixin classes. Here’s our views.py module again.from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework import mixins from rest_framework import generics class SnippetList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)We’ll take a moment to examine exactly what’s happening here. We’re building our view using GenericAPIView, and adding inListModelMixin and CreateModelMixin.The base class provides the core functionality, and the mixin classes provide the .list() and .create() actions. We’re then explicitly binding the get and post methods to the appropriate actions. Simple enough stuff so far.class SnippetDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs)Pretty similar. Again we’re using the GenericAPIView class to provide the core functionality, and adding in mixins to provide the.retrieve().update() and .destroy() actions.
farsiUsing generic class based viewsUsing the mixin classes we’ve rewritten the views to use slightly less code than before, but we can go one step further. REST framework provides a set of already mixed-in generic views that we can use to trim down our views.py module even more.from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework import generics class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializerWow, that’s pretty concise. We’ve gotten a huge amount for free, and our code looks like good, clean, idiomatic Django.Next we’ll move onto part 4 of the tutorial, where we’ll take a look at how we can deal with authentication and permissions for our API.
farsiTutorial 4: Authentication & PermissionsCurrently our API doesn’t have any restrictions on who can edit or delete code snippets. We’d like to have some more advanced behavior in order to make sure that:Code snippets are always associated with a creator.Only authenticated users may create snippets.Only the creator of a snippet may update or delete it.Unauthenticated requests should have full read-only access.
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish
farsienglish

کنترل نسخه در GIT

کنترل نسخه در GIT :
بطور کلی کنترل نسخه یعنی دارا بودن تاریخچه ای از ویرایش هایی که روی یک یا چند فایل داشته‌ایم.
کنترل محلی نسخ :
روشی که اکثر کاربران از آن استفاده می‌کنند آرشیوگیری از سورس هایشان است که اصلاً مورد تأیید نیست و فضای زیادی را آشغال می نماید و همچنین خطاپذیری آن را بالا میبردراه حل :
برای حلی این موضوع برنامه نویسان دست به طراحی سیستم‌هایی زده‌اند که بانک اطلاعاتی از سورس های شما تهیه می نماید تا شما بتوانید در زمان کمتر و با کیفیت بهتر به تاریخچه های سورس خود دسترسی داشته باشد

سیستم‌های کنترل نسخه مرکزی:
اصلی‌ترین نیاز یک تیم همراه نسخه های واحد با یکدیگر است. اعضای تیم نسخه ی اصلی را از سرورهایی مانند Perforce, CVS, Subversion دریافت کرده و از تمام فایل‌ها userها در کامپیوتر خود checkout می نمایند و نگهداری می‌کنند
سیستم‌های کنترل نسخه پخشی:
برنامه نویس فقط اقدام به ذخیره سازی تاریخچه ی فایل خود نمی‌کند و هر گاه بخواهد کل مخزن را فراخوانی نموده و آخری تصویر از آن فایل را دریافت می‌کند به همین شکل اگر کاربر دیگری مشکل داشته باشد و سورس ها آسیب ببیند می‌تواند مجدداً خود را به تیم برساند. همچنین کاربرها می‌توانند در قالب گروه‌های مختلف با یکدیگر کارهایی که انجام می‌دهند را به اشتراک بگذارند
GIT چیست :
اصلی‌ترین تفاوت بین Git و دیگر VCSها (که شامل Subversion و هم خانواده های آن نیز می‌شود) دیدگاهی است که Git نسبت به داده‌های خود دارد. از نظر مفهومی، اکثریت دیگر سیستم‌ها اطلاعات را به مثابه لیستی از تغییرات بر مبنای فایل، ذخیره می‌کنند. این سیستم‌ها (CVS، Subversion، Perfoce، Bazaar و غیره) به اطلاعاتی که نگهداری می‌کنند به شکل مجموعه‌ای از فایل‌ها و تغییراتی که برروی هر فایل در مرور زمان انجام گرفته است، می‌نگرند.
دیدگاه Git نسبت به داده‌های خود به شکل تصاویر لحظه‌ای از یک سیستم فایلی کوچک است. هر زمانی که شخص commitای انجام می‌دهد یا وضعیت پروژه خود را در Git ذخیره می‌کند، در اصل تصویری از وضعیت تمامی فایل‌ها در لحظه موردنظر تهیه و ارجاعی به تصویر لحظه‌ای ایجاد شده ذخیره می شود. برای آن‌که این عمل به صورت بهینه انجام پذیرد، اگر در فایلی تغییری ایجاد نشده باشد، Git اقدام به ذخیره سازی مجدد فایل نمی‌کند – تنها پیوندی به نسخه مشابه آن فایل که قبلاً ذخیره شده است را ذخیره می کند
این شکل نگرش مهمترین اصل تمایز Git با دیگر VCSها است. این امر موجب می‌شود تا Git تجدیدنظری نسبت به تمامی ابعاد کنترل نسخه داشته باشد، که اکثریت دیگر سیستم‌ها از نسل‌های قبل از خود به ارث برده‌اند. این موضوع باعث شده است تا Git از یک VCS ساده، به سیستم فایلی کوچکی بدل شود که در بالادست آن ابزار قدرتمند باورنکردنی بنا شده است.
اکثر عملیاتی که در Git انجام می‌پذیرد جهت اجرا تنها نیازمند فایل‌ها و منابع محلی هستند – به‌طور کلی نیازمند هیچ‌گونه اطلاعاتی از کامپیوتری دیگر در شبکه نیست. اگر شما فردی هستید که به CVCSای عادت کرده‌اید که در آن اکثر فعالیت‌ها دارای افزونگی رکود شبکه‌ای داشته‌اند، شاید این مزیت Git این فکر را برای شما تداعی کند که خدایان سرعت Git را با قدرتی وصف ناشدنی مورد لطف و رحمت قرار داده‌اند. از آن جهت که تمامی تاریخچه پروژه برروی دیسک محلی قرار دارد، به نظر می‌رسد که اکثر عملیات به صورت لحظه‌ای و بلادرنگ انجام می‌پذیرند.
به عنوان مثال، Git برای نمایش تاریخچه پروژه نیازی جهت مراجعه به سرور برای اخذ تاریخچه و نمایش آن ندارد – Git این عمل را با خواندن مستقیم پایگاه داده محلی انجام می‌دهد. این بدان معناست که شخص می‌تواند تاریخچه پروژه را تقریباً بلادرنگ مشاهده کند. اگر نیاز به مشاهده تغییرات بین نسخه فعلی یک فایل با نسخه یک ماه قبل از آن باشد، Git می‌تواند به‌جای آن‌که از سرور درخواست این عمل را داشته باشد و یا آن‌که نسخه قبلی را از سرور خارجی فراخوانی و سپس مقایسه محلی را انجام دهد، این عمل را با نگاهی به نسخه یک ماه قبل فایل و انجام محاسبات محلی تغییرات رخ داده، انجام می‌دهد.
همچنین بدین معناست که در صورت آفلاین بودن و یا وصل نبودن به VPN دامنه عملکرد شخص زیاد محدود نمی‌شود. اگر سوار بر هواپیما یا قطار شده باشید و تصمیم به انجام کاری داشته باشید، می‌توانید به راحتی commit را انجام داده و زمانی که دسترسی به شبکه پیدا کردید آپلود را انجام دهید. اگر به خانه رفته باشید و قادر به فعال سازی VPN خود نشده باشید، باز هم وقفه‌ای در کار شما حاصل نمی‌شود. در اکثریت دیگر سیستم‌ها انجام این موارد غیرممکن یا به سختی انجام می‌پذیرد. به عنوان مثال در Perforce، در صورتی که به شبکه متصل نباشید در واقع توانایی انجام کاری نخواهید داشت؛ در Subversion و CVS، امکان دست‌کاری فایل‌ها برای شما وجود دارد، ولی برای commit تغییرات روی پایگاه داده محدودیت دارید (زیرا اتصال شما به پایگاه داده بر قرار نیست). شاید این موضوع مسئله مهمی به نظر نیاید، ولی شاید با مشاهده تفاوت‌های بزرگی که می‌تواند به موجب آن ایجاد شود، شگفت زده شوید.
هرچیزی که بخواهد در Git ذخیره شود، ابتدا checksum آن محاسبه می‌شود و سپس به‌وسیله همین checksum ارجاع داده می‌شود. چنین عملی موجب می‌شود که در صورت ایجاد کوچکترین تغییری در محتویات فایل یا پوشه‌ای، Git از آن آگاهی پیدا کند. این دستورالعمل در Git در پایینترین سطح پیاده‌سازی شده است و تأییدی بر صحت فلسفه Git دارد. بدین دلیل است که اگر داده‌ای در حین انتقال از دست برود و یا فایلی مخدوش شود، Git به سرعت از آن اطلاع پیدا می‌کند.
مکانیزمی که Git برای تولید checksum استفاده می‌کند، هش SHA-1 است. این هش یک رشته 40 کاراکتری از کاراکترهای مبنای شانزده است (0 – 9 و a – f) که از روی محتویات فایل و یا ساختار پوشه موردنظر در Git محاسبه می‌گردد. در ادامه یک نمونه از هش SHA-1 آورده شده است:
24b9da6552252987aa493b52f8696cd6d3b00373
به علت استفاده زیاد Git از این هش، به کرات در جای جای Git مشاهده‌گر این هش‌ها خواهید بود. در واقع، Git از نام فایل برای ذخیره‌سازی آن استفاده نمی‌کند بلکه Git از هش تولید شده از محتویات فایل مربوطه برای آدرس دهی آن در پایگاه داده خود بهره می‌گیرد.
هرگاه عملی در Git انجام می‌پذیرد، تقریباً در تمامی موارد Git داده‌ای به داده‌های خود در پایگاه داده اضافه می‌کند. انجام دادن عملی در این سیستم که برگشت‌پذیر نباشد یا باعث حذف داده ای از سیستم شود، بسیار سخت است. مشابه اکثر VCSها، فرد می‌تواند تا قبل از commit هرگونه تغییراتی را انجام دهد؛ ولی به محض commit یک تصویر لحظه‌ای در Git، امکان حذف آن بسیار سخت است، مخصوصاً اگر فرد عادتاً پایگاه داده خود را به مخزن دیگری push کند.
این قابلیت باعث می‌شود که استفاده از Git، به عملی فرح بخش تبدیل شود زیرا فرد خواهد توانست بدون در خطر انداختن چیزی دست به هرگونه آزمایشی بزند. برای آشنایی بیشتر با چگونگی ذخیره‌سازی و بازیابی داده‌ها در Git که به نظر از دست رفته می‌باشند
توجه، توجه. اگر می‌خواهید پروسه یادگیری Git را بدون دردسر ادامه دهید، این بخش را به دقت مطالعه کنید. فایلها در Git می‌توانند در سه وضعیت اصلی قرار داشته باشند: committed، modified و staged. committed بدین معناست که فایل موردنظر در پایگاه داده محلی ذخیره شده است. modified یعنی تغییری در فایل ایجاد شده است ولی هنوز commitای از این فایل روی پایگاه داده انجام نگرفته است. فایلی که در وضعیت staged قرار گرفته است، فایلی تغییر یافته است که نسخه فعلی آن در تصویر لحظه‌ای بعدی جهت commit نشانه‌گذاری شده است.
حال می‌توان سه بخش اصلی پروژه Git را معرفی کرد: پوشه Git، پوشه در حال کار (working directory) و staging area.
در Git، metadata و پایگاه داده پروژه در پوشه Git ذخیره می‌شوند. این قسمت مهمترین بخش Git است، در واقع هنگامی که از مخزن کامپیوتری cloneای گرفته می‌شود، کپی از این پوشه ایجاد می‌گردد.
پوشه در حال کار، checkout منفردی از نسخه‌ای از پروژه است. فایل‌های این بخش، فایل‌هایی می‌باشند که از پایگاه داده فشرده واقع در پوشه Git بیرون کشیده شده و جهت استفاده و ایجاد تغییر بر روی دیسک قرار داده شده‌اند.
staging area عموماً از یک فایل ساده تشکیل شده است که محتوی اطلاعاتی است که مشخص می‌کند که چه چیزهایی در commit بعدی قرار می‌گیرند. معمولاً این فایل را index می‌نامند ولی عبارت staging area نیز در حال تبدیل شدن به نامی استاندارد برای چنین فایلی است.
روند کاری Git عموماً به صورت ذیل است:
1. ایجاد تغییرات روی فایل‌های واقع در پوشه در حال کار.
2. stage کردن فایل‌ها و اضافه کردن تصاویر لحظه‌ای فایلها به staging area.
3. commit کردن، که به موجب آن وضعیت فعلی فایل‌ها در staging area تحت یک تصویر لحظه‌ای به صورت دائمی در پوشه Git ذخیره می‌گردد.
اگر نسخه‌ای از یک فایل در پوشه git قرار داشته باشد، commit شده فرض می‌شود. اگر تغییری در فایل ایجاد شده باشد و به staging area اضافه شده باشد، گوییم staged شده است. و اگر در فایل از آخرین مرتبه‌ای که checkout شده است تغییری ایجاد شده باشد ولی staged نشده باشد، گوییم modified شده است.
تنظیمات شروع به کار Git
حال که Git روی سیستم نصب شده است، نیاز به شخصی‌سازی بعضی از منابع Git است. انجام این تنظیمات فقط برای یک مرتبه انجام می‌پذیرد؛ و بعد از آن با هر بار ارتقاء بدون تغییر باقی می‌مانند. همچنین امکان تغییر آن‌ها در هر زمانی که نیاز باشد به کمک خط فرمان وجود دارد.
به همراه Git ابزاری ارائه شده است با نام git config که امکان خواندن و اعمال متغیرهای تنظیماتی که تمامی ابعاد ظاهری و عملیاتی Git را کنترل می‌کند فراهم می‌سازد.
فایل /etc/gitconfig: حاوی مقادیر تمامی کاربران سیستم و مخازن آن‌ها است. اگر به همراه git config از گزینه –system استفاده شود، خواندن و نوشتن به صورت اختصاصی از این فایل انجام می‌پذیرد.
فایل ~/.gitconfig: مختص کاربر مشخصی است. با استفاده از گزینه –global خواندن و نوشتن Git به صورت اختصاصی از این فایل انجام می‌پذیرد.
فایل config موجود در پوشه git (.git/config) یا هر مخزنی که در حال استفاده از آن می‌باشید: مختص یک مخزن خاص است. مقادیر هر سطح باعث لغو مقادیر سطح قبلی خود می‌شود. بنابراین مقادیر .git/configموجب لغو مقادیر /etc/gitconfig خواهد شد.
در سیستم‌های ویندوزی، Git در پوشه $HOME (متغیر محیطی %USERPROFILE% در ویندوز) که برای اکثر کاربران با توجه به نسخه سیستم در مسیرهای C:\Documents and Settings\$USER‍ یاC:\Users\$USER($USER‍ در ویندوز متغیر محیطی %USERNAME%) قرار دارد، فایل .gitconfig را جستجو می‌کند. همچنین نسبت به مسیر ریشه MSys که همان مسیر نصب انتخاب شده در هنگام اجرای نصاب Git در ویندوز می‌باشد، به دنبال فایلی با نام /etc/gitconfig می‌گردد.شناسه کاربر
اولین عملی که بعد از نصب Git باید انجام شود، مقداردهی دو متغیر نام کاربری (user name) و آدرس پست الکترونیکی (e-mail address) است. این عمل از آن جهت اهمیت دارد که در هر commit این اطلاعات به‌صورتی تغییر ناپذیر روی commit انجام شده حک می‌شوند.

$ git config --global user.name "John Doe"

$ git config --global user.email johndoe@example.com

مجدداً یادآوری می‌شود که انجام این عمل در صورت استفاده از گزینه –global فقط یک مرتبه انجام می‌پذیرد، زیرا Git برای هر عملی که در سیستم انجام می‌پذیرد از این اطلاعات استفاده می‌کند. حال اگر فرد نیاز به استفاده از نام و آدرس پست الکترونیکی متفاوتی برای پروژه‌های خاصی دارد، می‌تواند با اجرای همان دستورات البته بدون استفاده از گزینه –global هنگامی که در مسیر پروژه مذکور قرار دارد به مقصود خود دست یابد.

ویرایشگر کاربر
حال که شناسه تنظیم شد، می‌توان ویرایشگر متن پیش فرضی را معرفی کرد تا هنگامی که نیاز به درج پیغامی در Git است فراخوانی شود. به صورت پیش فرض Git از ویرایشگر پیش فرض سیستم برای این امر استفاده می کند، که معمولاً Vi یا Vim است. اگر نظر شخص به استفاده از ویرایشگر متنی متفاوتی مانند Emacs باشد، می‌توان به صورت ذیل عمل کرد:

$ git config --global core.editor emacs

ابزار Diff

ابزار مفید دیگری که شاید نیاز به تنظیم داشته باشد، ابزار diff پیش فرضی است که برای رفع مغایرت ایجاد شده در هنگام اجرای دستور merge استفاده می‌گردد. به عنوان مثال اگر هدف استفاده از vimdiff باشد خواهیم داشت:

$ git config --global merge.tool vimdiff

Git از ابزارهای kdiff3، tkdiff، meld، xxdiff، emerge، vimdiff، gvimdiff، ecmerge و opendiff جهت merge پشتیبانی می‌کند. با این وجود امکان تعریف ابزاری شخصی نیز وجود دارد؛ برای اطلاعات بیشتر جهت انجام این مورد می‌توانید به فصل 7 مراجعه کنید.
بررسی تنظیمات
برای مشاهده و بررسی تنظیمات، می‌توان از دستور git config –list استفاده کرد که در نتیجه آن Git تمامی تنظیمات موجود تا آن لحظه را در قالب لیستی نمایش می‌دهد:

$ git config --list

user.name=Scott Chacon

user.email=schacon@gmail.com

color.status=auto

color.branch=auto

color.interactive=auto

color.diff=auto

...

احتمال دارد در این لیست کلیدهایی بیش از یک بار مشاهده شوند، دلیل این امر آن است که Git کلید مشابهی را از فایل‌های مختلفی (مانند /etc/giconfig و ~/.gitconfig) خوانده است. در این‌گونه موارد، Git آخرین مقدار کلید منحصر به فردی که مشاهده می‌کند را جهت استفاده به‌کار می‌گیرد.

همچنین برای مشاهده مقدار مورد استفاده یک کلید خاص توسط Git، می‌توان از دستور git config {key}استفاده کرد:

$ git config user.name

Scott Chacon

سرویس ها در AngularJS

۱- AngularJS Service / Factory Tutorial با مثال
وظیفه ی سرویس ها در انگولار انجام وظائف محوله است!
این سرویس ها وظیفه ی انجام یک سری کارهای مربوط به لایه ی تجاری نرم‌افزار شما را بر عهده دارند. در طراحی انگولار موارد نگران کننده ی برنامه شما از هم جدا می‌شوند. کنترلر شما باید مسئول اتصال داده‌ها از model به view را از طریق $scope داشته باشد. البته این نوع انتقال شامل انتقال منطق نیست ، یک نوع واکشی داده یا دستکاری آن است. حالا اینجا لازم است یک لایه که شامل توابعی است که محاسبات را انجام می‌دهد به برنامه اضافه شود و آن هم سرویس ها هستند.انگولار امکانات مختلفی برای مدیریت این لایه در نظر گرفته است.هر گاه می‌خواهیم از سرویس ها استفاده نماییم ، فقط می بایست نام آن را صدا بزنیم و سپس انگولار یک مدل تزریق جادویی ، اشیاء سرویس را برای شما وارد یا تزریق می‌کند که شامل یک شی stateless بوده و شامل یک سری توابع کاربردی هستند. این توابع از هر جایی قابل فراخوانی هستند مثل Controllers, Directive, Filters and … در نتیجه می‌توانیم برنامه خود را یک سری یونیت های منطقی تقسیم کنیم.پس می‌توانیم در منطق تجاری خود یک سری url استفاده نماییم که داده‌ها را از سرویس دریافت می‌کنند و در آبجکت های سرویس قرار میدهند.
قرار دادن منطق های تجاری نرم‌افزار در لایه‌ای جداگانه مزایای فراوانی دارد. بعنوان اولین مورد می‌توان به تفکیک وظائف و نوعی تبعیض وظیفه در نرم‌افزار رسید که کار کنترل محاسبات را ساده‌تر می کند. دوم در این روش می‌توان موقعیت های بیشتری را برای تست پذیر بودن برنامه بوجود آورد.

شکل بالا را در نظر بگیرید. ما برنامه ی خود را به کنترلر تقسیم کرده ایم: ۱- پروفایل ۲-داشپورد .
هر کدام از این کنترلر ها نیاز به یک سری داده‌های خاص از سرور دارند. لذا بجای تکرار مکررات فراخوانی داده‌ها در ویو ها ما یک سوریس بنام User Service ساخته و مسائل مربوط به سرور را از آن طریق حل می کنیم. و از این روش حداقل پیچیدگی در فراخوانی های تکراری را کمتر می‌کنیم.
انگولار بصورت خودکار User Service را در پروفایل وداشبورد تزریق خواهد کرد و این تزریق خودکار امکان تست پذیری لایه ها و ابجکت ها را ساده‌تر می نماید.

۲- سرویس های توکار انگولار
انگولار بصورت خود دارای سرویس های مختلفی است که در برنامه‌هایمان قابل استفاده هستند.مثل $http ضمناً تمامی این سرویس های داخلی با $ شروع میشوند.البته سرویس های دیگری نیز وجود دارند مثل $route, $window, $location و غیره.
این سرویس ها را می‌توان بوسیله ی تمامی کنترل های که این سرویس ها بعنوان وابسته معرفی می نمایند فراخوانی نمود مثل :

module.controller('FooController', function($http){
//...
});

module.controller('BarController', function($window){
//...
});

۳- سرویس های دستی در انگولار
در انگولار می‌توان سوریس هایی که خود طراحی می‌کنیم را هر جایی که لازم دانستیم فراخوانی نماییم.
روش‌های مختلفی برای فراخوانی سرویس های انگولار وجود دارند. دو روش زیر از ساده‌ترین ها هستند :

var module = angular.module('myapp', []);

module.service('userService', function(){
this.users = ['John', 'James', 'Jake'];
});

یا می‌توان از متد factory استفاده نمود.

module.factory('userService', function(){

var fac = {};

fac.users = ['John', 'James', 'Jake']; 

return fac;

});

این دو روش برای فراخوانی سرویس ها بکار برده میشوند.البته به تفاوت‌های بین factory() و service() اشاره خواهد شد. البته باید توجه داشت که هر دوی این روش‌ها بعنوان ساخت یک سرویس معرفی شده‌اند و در همه جا قابل دسترس هستند مثل : controllerها فیلترها ، Directives و …
۴- تفاوت بین Factory و Services در انگولار
سرویس های توکار انگولار همانطور که قبلاً اشاره شد اشیایی تک قلو هستند. این در نرم‌افزار کاربرد گسترده ای دارند. لذا این شی سرویس یکبار ایجاد شده و همه جا می‌توان استفاده نمود.
همانطور که اشاره شده است دو روش برای ساخت سرویس ها وجود دارد . استفاده از module.factory و module,service

module.service( 'serviceName', function );

module.factory( 'factoryName', function );

وقتی نام سرویس بعنوان یک آرگومان قابل تزریق در ویو شما قرار داده می‌شود شما یک نمونه از تابع را برای خود فراهم می آورید. به عبارت دیگر تابع YouPassedToService() را درنظر بگیرید. این نمونه از شی بعنوان یک شی در سرویس قرارداده شده و انگولار آن را در سرویس ها ثبت نموده تا بتوان آن را در سایر سرویس ها و کنترلر ها استفاده نمود.
ولی وقتی از factoryName بعنوان یک سرویس فراخوانی می‌شود تنها نتیجه ی سرویس بازگشت داده شده و یک نمونه از شی فراخوانده نمی شود.
در مثال زیر MyService به دو روش مختلف فراخوانده شده است.

AngularJS .service

module.service('MyService', function() {
this.method1 = function() {
//..
}

this.method2 = function() {
//..
}
});
AngularJS .factory

module.factory('MyService', function() {

var factory = {}; 

factory.method1 = function() {
//..
}

factory.method2 = function() {
//..
}

return factory;
});

۵- تزریق وابستگی‌ها در سرویس ها
انگولار ابزارهایی را برای مدیریت وابستگی‌ها فراهم آورده است. در ویکی پدیا تزریق وابستگی اینگونه تفسیر شده است:
تزریق وابستگی الگویی برای طراحی نرم‌افزار است که اجازه می‌دهد تا واسط ها و وابستگی‌های پیچیده و کد بر کم شده و اجازه میدهد در حال اجرا آن را تغییرداده و یا با مدل های مختلف بکار برد.
در مثال‌های بالا نحوه ی تزریق وابستگی و مدیریت آن‌ها اشاره شد. ما $scope را کلاس کنترلر بکار بستیم.

حالا یک مثال عملی میزنیم تا کمی کنترل ها و سرویس ها را استفاده نماییم.

1- MathService : یک سرویس ساده دارای متدهای add , subtract , multiply and devide البته در این مثال فقط از multiply‌استفاده خواهیم کرد

2- CalculatorService :‌دارای دو متد square and cube

3- CalculatorController : این هم یک کنترلر ساده است برای عملیات های کاربر. برای UI مل یک TextBox داریم که کاربر یک عدد را وارد نموده و سپس با دو دکمه square and multiply آنرا مشاهده خواهد نمود.

۵-۱- HTML

<div ng-app="app">
    <div ng-controller="CalculatorController">
        Enter a number:
        <input type="number" ng-model="number" />
        <button ng-click="doSquare()">X<sup>2</sup></button>
        <button ng-click="doCube()">X<sup>3</sup></button>
        
        <div>Answer: {{answer}}</div>
    </div>
</div>

۵-۲- جاوا اسکریپت

var app = angular.module('app', []);

app.service('MathService', function() {
    this.add = function(a, b) { return a + b };
    
    this.subtract = function(a, b) { return a - b };
    
    this.multiply = function(a, b) { return a * b };
    
    this.divide = function(a, b) { return a / b };
});

app.service('CalculatorService', function(MathService){
    
    this.square = function(a) { return MathService.multiply(a,a); };
    this.cube = function(a) { return MathService.multiply(a, MathService.multiply(a,a)); };

});

app.controller('CalculatorController', function($scope, CalculatorService) {

    $scope.doSquare = function() {
        $scope.answer = CalculatorService.square($scope.number);
    }

    $scope.doCube = function() {
        $scope.answer = CalculatorService.cube($scope.number);
    }
});

۵-۳- دموی آنلاین

و مثالی دیگر :

AngularJS Controller

کنترلر ها هیچ چیزی جز توابع ساده جاوا اسکریپت نیستند که به یک اسکوپ متصل هستند. Controllers منطق را به view اهدا میکنند.۱- اسکوپ ها چیستند ؟اسکوب در ویو و کنترلر فعالیت می کند. این شی داده هایی را در خود نگه می دارد که قرار است به view‌ تحویل داده شوند. اسکوب ها از اتصال داده ی دو طرفه ی مخصوص انگولاری استفاده میکند که دیتای مدل ها را به view‌ می رساند.پس می توان این گونه نتیجه گرفت که اسکوب شی ای است که کنترلر را به view متصل می کند. به همین منظور این وظیفه ی کنترلر است که داده هایی که قرار است در view نمایش داده شوند را به به ان برساند.این عملیات ها تماما در $scope انجام میشوند.

حالا مثال کوچکی از این ارتباط میزنم :

<!DOCTYPE html>
<html ng-app>
<head>
<title>Hello World, AngularJS - ViralPatel.net</title>
<script type="text/javascript" 
	src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body>
<div ng-controller="ContactController">
	 Email:<input type="text" ng-model="newcontact"/>
	<button ng-click="add()">Add</button>
	<h2>Contacts</h2>

	<ul>
		<li ng-repeat="contact in contacts"> {{ contact }} </li>
	</ul>

</div>
<script type="text/javascript">
	function ContactController($scope) {
	    $scope.contacts = ["hi@email.com", "hello@email.com"];

	    $scope.add = function() {
		$scope.contacts.push($scope.newcontact);
		$scope.newcontact = "";
	    }
	}
</script>
</body>
</html>

۱.۱. دموی آنلاین :

در مثال بالا یک دکمه ی ساده در نظر گرفته شده است تا با فشردن آن محتوای آن در یک آرایه قرار گرفته و در یک لیست به نمایش گذاشته میشود.

۱.۲- ng-controller

این خصیصه همانطور که در مثال بالا هم قابل مشاهده است وظیفه ی معرفی یک کنترلر به view را دارد. در مثال بالا ما کنترلری بنام ContactController در یک Div بوسیله ی ng-controller تعریف نموده ایم. لذا هر گاه ما به درون Div سر سرک بکشیم با حاکمیت کنترلر ContactController در ارتباط خواهیم بود.

ContactController چیزی جز یک تابع ساده ‌vanilla JavaScript  نیست. در دموی بالا ما این کنترلر را بصورت یک تابع بکار بستیم.  در تابع ContactController شی ای بنام $scope بعنوان ارگومان در نظر گرفته شده است که همان وظیفه ی اتصال کنترلر به ویو را بر عهده دارد. وقتی انگولار این کنترلر را ساخت و پرداخت می کند بوسیله $scope بصورت خودکار در ویو پیاده سازی شده و تزریق میشود.

۱.۳- ng-repeat

در مثال بالا به نحوه ی نمایش contacts با استفاده از ng-repeat اشاره می کنیم.

	<li ng-repeat="contact in contacts">{{ contact }}</li>

ng-repeat یکی از پر کاربردترین خصیصه ها در ویوهای انگولاری است. این خصیصه یک آرایه را دریافت کرده و به تعداد آنها المنت های زیر شاخه ی خود را ساخته و تکرار میکند.

از این خصیصه در نشان دادن جداول ، گرید ها و … استفاده میکنند

۲- ساخت و پرداخت یک شی در اسکوپ

$scope.contacts = ["hi@email.com", "hello@email.com"]

با توجه به مثال بالا هرگاه می خواهیم یک برنامه با انگولار بسازیم می بایست وضعیت scope‌انگولار را روشن نماییم.

در مثال بالا در اسکوب هایمان لیستی از ایمیل های مختلف را در اسکوب contacts قرارداده ایم. وقتی انگولار این خط را بررسی می کند در سرویس $scope شی contacts از نوع آرایه را ساخته و ایمیل ها نسبت می دهد و آماده می شوند تا بروزرسانی ، حذف و یا در لیستی بوسیله ی ng-repeat قرارداده شوند.

انگولار نوع زیبایی از ارتباط بین کنترلر و ویو برقرار می کند که امکان میدهد امکان میدهد گاهی کنترلر دیتای درون contacts را دستکاری نماید و گاهی نیز view ، این نیز یکی از امکانات بسیار زیبای انگولار است.

۲.۱- ng-click

در مثال بالا ما یه متد به شکل زیر داریم

$scope.add = function() {
		...
	}

بوسیله ی ng-click می توان آنرا اجرا نمود. در اصل این خصیصه یه onClick یک المنت متصل شده است. ضمنا اینگونه توابع نیز در اسکوب نوشته میشوند

در این تابع ما به آرایه ی contacts نام جدیدی را push میکنیم و به محض اضافه سازی می توان آنرا در لیست مشاهده نمود

زیبا نیست :)))

۳- چگونه یک کنترلر را پیاده سازی نماییم

کمی درباره ی اینکه کنترها چگونه هستند صحبت و اشاره شد که این توابع تنها توابع ساده vanilla JavaScript هستند که مقداری کدهای تجاری در آن وارده شده و به ویو متصل می شوند.

function ContactController($scope) {

	//...

}

روشی که در مثال بالا بکار بسته شد ساده ترین روش استفاده ی کنترلر است ولی پیشنهاد می کنم اینگونه آنرا بکار نبرید.

روش بهتری برای استفاده پیاده سازی وجود دارد که در ادامه اشاره خواهد شد. این روش بما اجازه میدهد که کنترلرها را همراه با Module‌ها پیاده سازی کنیم که روشی است استاندارد.

۳.۱- AngularJS Modules

مدل ها یک موجودیت منطقی هستند که شما تصمیم می گیرید به چه تعداد و چگونه بکار ببندید به همین ترتیب برنامه شما می تواند تعداد متعددی module داشته باشد باشد مثل Transaction, Report, … هر ماژول نمایان گر یک موجودیت منطقی در برنامه شماست.

هر مدل می تواند دارای چندیدن کنترلر باشد. همانطور که در شکل بالا مشاهده می کنید. پس می توان یک یا چند کنترلر به یک مدل اضافه کرد. حالا یک نمونه را مشاهده می کنیم :

var myApp = angular.module('myApp',[]);
 
myApp.controller('ContactController', ['$scope', function($scope) {
	$scope.contacts = ["hi@email.com", "hello@email.com"];

	$scope.add = function() {
		$scope.contacts.push($scope.contact);
		$scope.contact = "";
	}
}]);

در مثال بالا مدلی بنام myApp بوسیله ی angular.module() ساختیم. سپس یک کنترلر بنام ContactController به آن افزدیم. البته این روش هم یکی از روش های موجود برای این کار است که من همین روش را پیشنهاد میکنم.

به نحوه ی تعریف کنترل ها در myApp.controller() توجه نمایید. ما یک آرای به آن اضافه کردیم که یکی و تنها آرایه استفاده شده در آن $scope است و نام سرویس های عمومی انگولار است و ارگومان بعدی ContactController‌ است مربوط به شرح توابع مربوط به کنترلر در آن قرار میگیرد.

۴- Nested Controllers

انگولار از کنترلرهای تو در تو نیز پشتیبانی می کند :

<div ng-controller="CarController">
	My name is {{ name }} and I am a {{ type }}
	
	<div ng-controller="BMWController">
		My name is {{ name }} and I am a {{ type }}

		<div ng-controller="BMWMotorcycleController">
			My name is {{ name }} and I am a {{ type }}

		</div>
	</div>
</div>

<script>
function CarController($scope) {

	$scope.name = 'Car';
	$scope.type = 'Car';

}

function BMWController($scope) {

	$scope.name = 'BMW';

}

function BMWMotorcycleController($scope) {

	$scope.name = 'BMWMotorade';
	$scope.type = 'Motorcycle';

}


</script>

دموی آنلاین :

۵- وراثت در کنترلر ها

هنگام استفاده از کنترلهای تو در تو ممکن است بخواهید از قدرت وراثت در کنترل های انگولار استفاده نمایید.

ممکن است شما BaseController‌ داشته باشید و مابقی کنترل ها نیز زیر شاخه ی آن باشند.

برای استفاده از این امکان شما میبایست از سرویس $injector استفاده نمایید :

<div ng-controller="BMWController">
	
	My name is {{ name }} and I am a {{ type }}

	<button ng-click="clickme()">Click Me</button> 

</div>
    

<script>
function CarController($scope) {
 
	$scope.name = 'Car';
	$scope.type = 'Car';
 
	$scope.clickme = function() {
		alert('This is parent controller "CarController" calling');
	}

}
 
function BMWController($scope, $injector) {
    
    $injector.invoke(CarController, this, {$scope: $scope});
    
    $scope.name = 'BMW';
 
}
</script>

و در آخر یه پروژه ی نمونه دیگر :

لطفا بروی این پروژه متمرکز شوید :


Play on JSFiddle – http://jsfiddle.net/viralpatel/JFYLH/

AngularJS Routing and Views

روترها بشما کمک می کنند تا برنامه ی خود را به ویو های مختلف تقسیم کرده و آنها را به کنترلر های مختلف متصل نمایید

 در شکل بالا ما دو Route url به نام های /ShowOrders و /AddNewOrder ایجاد کردیم. هر کدام از این نقاط مربوط به ویو های خاصی سات و بوسیله ی کنترلر خود مدیریت میشوند. 
۱- معرفی $routeProviderامکانات بسیار کاربردی انگولار در سرویسی بنام $routeProvider مهیا شده است. استفاده از این سرویس استفاده تنگاتنگ کنترلر ، ویو ، تمپلیت و مدیریت URL را بهینه نموده است. استفاده از این امکان نیز برای مرورگر بهینه شده است تا با استفاده از دکمه back  or forward مدیریت نرم افزار به هم نخورد.نحوه ی ایجاد روتینگدر نمونه سورس پایین اشاره ای به نحوه ی نگاشت روتینگ شده است. در مثال زیر .when() and .otherwise() برای شرح روتینگ در نظر گرفته شده است.

var sampleApp = angular.module('phonecatApp', []);
 
sampleApp .config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/addOrder', {
        templateUrl: 'templates/add-order.html',
        controller: 'AddOrderController'
      }).
      when('/showOrders', {
        templateUrl: 'templates/show-orders.html',
        controller: 'ShowOrdersController'
      }).
      otherwise({
        redirectTo: '/addOrder'
      });
  }]);

در نمونه کد بالا ما دو url داریم /addorder and /showOrder و آنها را به ویو های templates/add-order.html and template/show-orders.html اتصال داده ایم. هر گاه  http://app/#addOrder را در مرورگر باز کنیم، انگولار بصورت خودکار این آدرس را با روت های انگولار چک کرده و add-order.html را فراخوانی می کند و سپس AddOrderController را به ویو اضافه می نماید.

۱.۱- اولین پروژه با AngularJS + Routing

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>AngularJS Routing example</title>
  </head>

  <body ng-app="sampleApp">

    <div class="container">
		<div class="row">
		<div class="col-md-3">
			<ul class="nav">
				<li><a href="#AddNewOrder"> Add New Order </a></li>
				<li><a href="#ShowOrders"> Show Order </a></li>
			</ul>
		</div>
		<div class="col-md-9">
		  	<div ng-view></div>
		</div>
		</div>
    </div>
	<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
	<script src="app.js"></script>
  </body>
</html>

همانطور که مشاهده می کنید دو دکمه وجود دارد با لینک های #AddNewOrder  و #ShowOrders که هر کدام یک تمپلیت قرار است لود کنند.

ng-view

این تگ مشخص کننده محل لود شدن تمپلیت است و در اصل نوعی placeholder‌ است.

ng-view را می توان به یکی از صورت های زیر در تمپلیت اصلی تعرف نمود

<div ng-view></div>
..
<ng-view></ng-view>
..
<div class="ng-view"></div>

۱.۲- اضافه سازی Routing  در AngularJS

app.js :

//Define an angular module for our app
var sampleApp = angular.module('sampleApp', []);

//Define Routing for app
//Uri /AddNewOrder -> template add_order.html and Controller AddOrderController
//Uri /ShowOrders -> template show_orders.html and Controller AddOrderController
sampleApp.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/AddNewOrder', {
		templateUrl: 'templates/add_order.html',
		controller: 'AddOrderController'
	}).
      when('/ShowOrders', {
		templateUrl: 'templates/show_orders.html',
		controller: 'ShowOrdersController'
      }).
      otherwise({
		redirectTo: '/AddNewOrder'
      });
}]);


sampleApp.controller('AddOrderController', function($scope) {
	
	$scope.message = 'This is Add new order screen';
	
});


sampleApp.controller('ShowOrdersController', function($scope) {

	$scope.message = 'This is Show orders screen';

});

با توجه به syntax بالا ، با دانش کمی از زبان انگلیسی می توان فهمید که روتینگ قراره چه فعالیت هایی رو انجام میده ، این فوق العادست و همینطور ساده

۱.۳- اضافه کرده HTML Template files

با توجه به فایل app.js نیاز است دو فایل در تمپلیت داشته باشیم و این فایل ها می بایست partial بوده و بعنوان مثال بصورت زیر باشند ، البته مثال زیر بعنوان محتوای فایل templates/add_order.html در نظر گرفته شده است

templates/add_order.html

<h2>Add New Order</h2>

{{ message }}

templates/show_orders.html

<h2>Show Orders</h2>

{{ message }}

دموی آنلاین :

Demo link: Plnkr.co

۲- نحوه ارسال پارامترها در Route Urls

با توجه به شکل بالا می خواهیم با کلیک بروی هر سفارش کاربر بتواند جزئیاتی از سفارش مورد نظر را مشاهده نماید. به همین خاطر نیاز است کد سفارش همراه با روتر به کنترلر ارسال شده تا ویوی مورد نظر فراخوانی شود.

به سورس زیر دقت نمایید :

when('/ShowOrder/:orderId', {
      templateUrl: 'templates/show_order.html',
      controller: 'ShowOrderController'
});

:orderId همان محل قرار گیری کد است رو روتر می فهمد قرار است در اینجا چیزی نوشته شود که آنرا تحویل کنترلر دهد

حالا طبق مثال زیر کنترلر این ورودی را از روتر تحویل میگیرد :

...
$scope.order_id = $routeParams.orderId;
...

حالا با دقت به مثال دموی آنلاین توجه نمایید :

Demo link: Plnkr.co

۳- نحوه فراخوانی ویوهای محلی همراه تگ اسکریپت !!

قرار نیست همیشه تمپلیت شما از فایل های مختلفی تشکیل شود و Url شما فقط از یک سری partial files استفاده نماید ، می توان به در مواقعی که urlrouting‌ شما قرار است کد کوچکی را فراخوانی نماید که شما دیگر نیاز نبینید که در یک فایل جداگانه آنرا قرار دهید می توانید آنرا در بدنه صفحه ی اصلی خود بکار ببندید و از همان صفحه فراخوانی را انجام دهید

۳.۱- ng-template directive

<script type="text/ng-template" id="add_order.html">
	<h2> Add Order </h2>
	{{message}}
</script>

سورس بالا یک نمونه تمپلیت توکار است.

و حالا یک دموی آنلاین برای نمایش بهتر این امکان :

Demo link: Plnkr.co
۴- اضافه کردن داده به RouteProvider

همانطور که اشاره کردم $routePovider متدهای when and otherwise رو برای پیاده سازی url ها بکار میبره. در مواقعی نیاز هست که ما می خواهیم بجز url query داده های دیگری را به controller‌از طریق روت برسونیم. مثلا شاید شما از یک کنترلر برای چند قسمت مختلف می خواهید استفاده کنید.

به مثال زیر توجه کنید :

when('/AddNewOrder', {
	templateUrl: 'templates/add_order.html',
	controller: 'CommonController',
	foodata: 'addorder'
}).
when('/ShowOrders', {
	templateUrl: 'templates/show_orders.html',
	controller: 'CommonController',
	foodata: 'showorders'
});

sampleApp.controller('CommonController', function($scope, $route) {
	//access the foodata property using $route.current
	var foo = $route.current.foodata;
	
	alert(foo);
	
});

در مثال بالا foodata بعدا بوسیله ی controller قابل دریافت خواهد بود. و کنترلر نیز بوسیله $route.current.foodata به آن خواهد رسید.