From e8b4fe90367399c4c5c970d922007446897fb6cd Mon Sep 17 00:00:00 2001 From: user Date: Sun, 27 Oct 2013 04:57:15 +0600 Subject: [PATCH] add 'coding' declaration into .py files remove find operator from model to model manager add urls file in codes module clean views.py in codes module --- codeparser/codeparser/items.py | 1 + codeparser/codeparser/pipelines.py | 2 + codeparser/codeparser/settings.py | 1 + codeparser/codeparser/spiders/codes_spider.py | 1 + codes/forms.py | 23 +++++++- codes/managers.py | 52 +++++++++++++++++ codes/models.py | 42 ++------------ codes/urls.py | 7 +++ codes/views.py | 58 +++++++++---------- scrapy_settings.py | 1 + settings.py | 2 +- urls.py | 3 +- utils/__init__.py | 1 + utils/exceptions.py | 1 + 14 files changed, 126 insertions(+), 69 deletions(-) create mode 100644 codes/managers.py create mode 100644 codes/urls.py diff --git a/codeparser/codeparser/items.py b/codeparser/codeparser/items.py index 4800b88..a182a80 100644 --- a/codeparser/codeparser/items.py +++ b/codeparser/codeparser/items.py @@ -1,3 +1,4 @@ +#coding:utf-8 from scrapy.item import Item, Field diff --git a/codeparser/codeparser/pipelines.py b/codeparser/codeparser/pipelines.py index 6aa62a4..89fa301 100644 --- a/codeparser/codeparser/pipelines.py +++ b/codeparser/codeparser/pipelines.py @@ -1,5 +1,7 @@ +#coding:utf-8 from codes.models import Operator + class ParserPipeline(object): def process_item(self, item, spider): operator = Operator(**item) diff --git a/codeparser/codeparser/settings.py b/codeparser/codeparser/settings.py index 8b7b160..f1fb723 100644 --- a/codeparser/codeparser/settings.py +++ b/codeparser/codeparser/settings.py @@ -1,3 +1,4 @@ +#coding:utf-8 # Scrapy settings for parser project # # For simplicity, this file contains only the most important settings by diff --git a/codeparser/codeparser/spiders/codes_spider.py b/codeparser/codeparser/spiders/codes_spider.py index f078e3f..567bb25 100644 --- a/codeparser/codeparser/spiders/codes_spider.py +++ b/codeparser/codeparser/spiders/codes_spider.py @@ -1,3 +1,4 @@ +#coding:utf-8 import re from scrapy.spider import BaseSpider from codeparser.items import ParserItem diff --git a/codes/forms.py b/codes/forms.py index e3d0dae..1c706ba 100644 --- a/codes/forms.py +++ b/codes/forms.py @@ -1,4 +1,25 @@ +#coding:utf-8 +import re from django import forms + +PHONE_CLEAN_REGEX = re.compile(r"\D") class PhoneForm(forms.Form): - phone = forms.CharField(max_length=20) \ No newline at end of file + """ + Form for check valid of phone number. + """ + phone = forms.CharField(max_length=20) + + def clean_phone(self): + """ + Validate phone value + """ + phone = self.cleaned_data["phone"] + + phone_no = PHONE_CLEAN_REGEX.sub(r'', phone) + + if len(phone_no) != 11: + raise forms.ValidationError(u"Invalid phone number") + + return phone_no + diff --git a/codes/managers.py b/codes/managers.py new file mode 100644 index 0000000..98bb261 --- /dev/null +++ b/codes/managers.py @@ -0,0 +1,52 @@ +#coding:utf-8 +from django.db import models +from utils.exceptions import OperatorNotFoundException + + +class OperatorManager(models.Manager): + """ + Manager class for operator model + """ + + def find(self, phone): + """ + Find phone operator by full identical + """ + country_code, cleaned = self._detect_phone_country(phone) + region_code, number = int(cleaned[:3]), int(cleaned[3:]) + + try: + operator = self.get(region_code=region_code, number_end_range__gte=number, number_start_range__lte=number) + except Exception, e: + return None + return operator + + def find_by_range(self, phone): + """ + Find phone operator by range identical + """ + country_code, number = self._detect_phone_country(phone) + + try: + operator = self.raw("""SELECT *, MAX(region_code) FROM codes_operator + WHERE number_start_range <= %s AND number_end_range >= %s""", [number, number])[0] + if operator.pk is None: + raise OperatorNotFoundException + except IndexError: + raise OperatorNotFoundException + + return operator + + def _detect_phone_country(self, value): + """ + Detect phone country by begin of number. If first number is 8 - number is RU + Return country and cleaned number. + """ + phone_str = str(value) + if phone_str[0] in ['7', '8']: + return 'RU', phone_str[1:] + + ### here need build logic of detect country + + return 'RU', phone_str[1:] + diff --git a/codes/models.py b/codes/models.py index 43309e4..5fae5e6 100644 --- a/codes/models.py +++ b/codes/models.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- import re +from .managers import OperatorManager from django.db import models -from utils.exceptions import InvalidNumberException, OperatorNotFoundException class Operator(models.Model): + """ + Model for desrcibe operator code info + """ name = models.CharField(max_length=250) region_code = models.PositiveIntegerField() number_start_range = models.PositiveIntegerField() @@ -13,40 +16,7 @@ class Operator(models.Model): region = models.CharField(max_length=250) country = models.CharField(max_length=4) + objects = OperatorManager() + class Meta: ordering = ['region_code', 'number_end_range'] - - @staticmethod - def _get_cleaned_number(number): - cleaned = re.sub(r'\D', r'', number) - - if len(cleaned) != 11: - raise InvalidNumberException - return cleaned - - @classmethod - def find(cls, phone): - cleaned = cls._get_cleaned_number(phone) - region_code = int(cleaned[1:4]) - number = int(cleaned[4:]) - region_operators = cls.objects.filter(region_code=region_code) - try: - operator = region_operators.filter(number_end_range__gte=number)[0] - if not operator.number_start_range <= number: - return None - except IndexError: - return None - return operator - - @classmethod - def find_by_range(cls, phone): - number = cls._get_cleaned_number(phone)[1:] # Убираем 8 с начала - - try: - operator = cls.objects.raw( - 'select *, max(region_code) from codes_operator where number_start_range <= %s and \ - number_end_range >= %s;', [number, number])[0] - except IndexError: - raise OperatorNotFoundException - - return operator diff --git a/codes/urls.py b/codes/urls.py new file mode 100644 index 0000000..de435e5 --- /dev/null +++ b/codes/urls.py @@ -0,0 +1,7 @@ +#coding:utf-8 +from django.conf.urls.defaults import patterns, url + + +urlpatterns = patterns('codes.views', + url(r'^$', 'show_operator'), +) diff --git a/codes/views.py b/codes/views.py index bf6d26d..f52a439 100644 --- a/codes/views.py +++ b/codes/views.py @@ -1,44 +1,42 @@ +#coding:utf-8 +from forms import PhoneForm +from models import Operator from utils import response_json from utils.exceptions import OperatorNotFoundException, InvalidNumberException -from models import Operator -from forms import PhoneForm def show_operator(request): + """ + Process request for get phone number code + """ try: - if request.method != 'POST': - form = PhoneForm(request.GET) - else: - form = PhoneForm(request.POST) - if form.is_valid(): - phone = form.cleaned_data['phone'] - - operator = Operator.find(phone) - - if not operator: - operator = Operator.find_by_range(phone) - - if operator: - response = { - 'status': 0, - 'message': 'ok', - 'phone': phone, - 'operator': operator.name, - 'region': operator.region, - 'region_code': operator.region_code, - 'mobile': operator.mobile, - 'country': operator.country, - } - else: - raise OperatorNotFoundException - - else: + form = PhoneForm(request.GET if request.method != 'POST' else request.POST) + + if not form.is_valid(): raise InvalidNumberException + phone = form.cleaned_data['phone'] + + operator = Operator.objects.find(phone) or Operator.objects.find_by_range(phone) + + if not operator: + raise OperatorNotFoundException + + response = { + 'status': 0, + 'message': 'ok', + 'phone': phone, + 'operator': operator.name, + 'region': operator.region, + 'region_code': operator.region_code, + 'mobile': operator.mobile, + 'country': operator.country, + } + return response_json(response) + except (OperatorNotFoundException, InvalidNumberException), e: return response_json({'status': 1, 'message': e.msg, 'code':e.code}) except Exception, e: return response_json({'status': 1, 'message': e}) - return response_json(response) diff --git a/scrapy_settings.py b/scrapy_settings.py index 0e89048..bf1749e 100644 --- a/scrapy_settings.py +++ b/scrapy_settings.py @@ -1,3 +1,4 @@ +#coding:utf-8 from settings import * diff --git a/settings.py b/settings.py index 8a933bc..2f00e83 100644 --- a/settings.py +++ b/settings.py @@ -1,4 +1,4 @@ -# Django settings for phonecodes project. +#coding:utf-8 import os project_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/urls.py b/urls.py index 39ba0ba..47a5ff8 100644 --- a/urls.py +++ b/urls.py @@ -1,6 +1,7 @@ +#coding:utf-8 from django.conf.urls.defaults import patterns, include, url urlpatterns = patterns('', - url(r'^$', 'codes.views.show_operator'), + url(r'^', include('codes.urls')), ) diff --git a/utils/__init__.py b/utils/__init__.py index cb1fa34..ef07aaa 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -1,3 +1,4 @@ +#coding:utf-8 import json from django.http import HttpResponse diff --git a/utils/exceptions.py b/utils/exceptions.py index 84444c9..07b5a9a 100644 --- a/utils/exceptions.py +++ b/utils/exceptions.py @@ -1,3 +1,4 @@ +#coding:utf-8 class InvalidNumberException(Exception): code = 1 msg = 'Invalid number.'