2011-01-29 30 views
8

Tôi có dạng Django trong đó một trong các trường là TextInput cho địa chỉ đường phố.Bình thường hóa địa chỉ đường phố ở Django/Python

Tôi muốn chuẩn hóa dữ liệu. Ví dụ:

>> normalize('420 East 24th St.') 
'420 E. 24th Street' 

>> normalize('221 Amsterdam Av') 
'221 Amsterdam Ave.' 

>> normalize('221 Amsterdam Avenue') 
'221 Amsterdam Ave.' 

Hoặc điều gì đó tương tự. Tôi đã sử dụng geopy để mã hóa địa lý. Có lẽ điều này có thể giúp đỡ?

Ngoài ra: Tôi nên chuẩn hóa ở đâu? Trong mô hình cơ sở dữ liệu hoặc trong chức năng sạch của trường biểu mẫu?

+0

Đối với quốc gia/quốc gia nào? – payne

+0

Xin lỗi: USA. Cụ thể là NYC. –

Trả lời

4

Cách đáng tin cậy nhất để thực hiện việc này là sử dụng dịch vụ xác minh địa chỉ thực hiện. Nó sẽ không chỉ tiêu chuẩn hóa (bình thường hóa) các thành phần địa chỉ theo tiêu chuẩn USPS (xem Publication 28) nhưng bạn cũng sẽ chắc chắn rằng địa chỉ này là có thật.

Tiết lộ đầy đủ: Tôi làm việc cho SmartyStreets, cung cấp chỉ một service như vậy. Dưới đây là một số trăn thực sự đơn giản mẫu mã cho thấy làm thế nào để sử dụng dịch vụ của chúng tôi thông qua một yêu cầu HTTP GET:

https://github.com/smartystreets/LiveAddressSamples/blob/master/python/street-address.py

+0

Tôi đang làm việc trên một thư viện phải xử lý các địa chỉ, và trong khi SmartyStreets trông hơi đắt tiền (mặc dù tầng miễn phí khá hào phóng) và có thể thêm một chút thời gian vào thư viện của tôi (yêu cầu một chuyến đi khứ hồi máy chủ), nó trông giống như một dịch vụ khá tuyệt vời. Tôi nghĩ rằng tôi có thể thêm hỗ trợ cho nó. * Hãy tiếp tục công việc tốt! * – bgw

+0

Cảm ơn! Mong bạn thông cảm, chúng tôi được phân phối theo địa lý và các yêu cầu được xử lý tại trung tâm dữ liệu gần nhất với vị trí của người dùng để giảm thời gian chờ. – mdwhatcott

2

Một tùy chọn sẽ là sử dụng Geopy để tra cứu địa chỉ trên một người như Yahoo hoặc Google Maps, sau đó sẽ trả về địa chỉ đầy đủ của một (s) mà họ khớp với địa chỉ đó. Bạn có thể phải xem số căn hộ bị cắt bớt trong địa chỉ được trả lại (ví dụ: "221 Amsterdam Av # 330" trở thành "221 AMSTERDAM AVENUE"). Ngoài ra, bạn cũng sẽ nhận được thông tin về thành phố/tiểu bang/quốc gia mà người dùng có thể đã viết tắt hoặc viết sai chính tả.

Trong trường hợp có nhiều kết quả phù hợp, bạn có thể nhắc người dùng phản hồi về địa chỉ của họ. Trong trường hợp không có kết quả phù hợp, bạn cũng có thể cho người dùng biết và có thể cho phép địa chỉ lưu, tùy thuộc vào mức độ quan trọng của địa chỉ hợp lệ và mức độ tin cậy bạn đặt vào tính hợp lệ của nhà cung cấp địa chỉ tra cứu.

Về làm bình thường này theo hình thức so với mô hình, tôi không biết những gì ưa thích Django chiều làm việc, nhưng sở thích của tôi là ở dạng, ví dụ:

def clean(self): 
    # check address via some self-defined helper function 
    matches = my_helper_address_matcher(address, city, state, zip) 
    if not matches: 
     raise forms.ValidationError("Your address couldn't be found...") 
    elif len(matches) > 1: 
     # add javascript into error so the user can select 
     # the address that matches? maybe there is a cleaner way to do this 
     raise forms.ValidationError('Did you mean...') 

Bạn có thể ném chức năng này tra cứu trong mô hình (hoặc một số tập tin helpers.py) trong trường hợp bạn muốn sử dụng lại nó trong các lĩnh vực khác

+1

Lời cảnh cáo, tôi đã sử dụng các dịch vụ này và chúng không phải là chính xác khủng khiếp, đặc biệt là với các căn hộ và phân khu. Ngoài ra, chúng rất khó, nếu không phải là không thể, sử dụng để xử lý các lô lớn. – Cerin

2

Đây là cách tôi đã kết thúc việc giải quyết này (không có ý định chơi chữ):

### models.py ### 

def normalize_address_for_display(address): 

    display_address = string.capwords(address) 

    # Normalize Avenue 
    display_address = re.sub(r'\b(Avenue|Ave.)\b', 'Ave', display_address) 

    # Normalize Street 
    display_address = re.sub(r'\b(Street|St.)\b', 'St', display_address) 

    # ...and other rules... 

    return display_address 

class Store(models.Model): 

    name = models.CharField(max_length=32) 
    address = models.CharField(max_length=64) 
    city = models.CharField(max_length=32) 
    state = models.CharField(max_length=2) 
    zipcode = models.CharField(max_length=5) 

    @property 
    def display_address(self): 
     return normalize_address_for_display(self.address) 

Sau đó tôi sử dụng Place.display_address trong các mẫu. Điều này cho phép tôi giữ dữ liệu người dùng ban đầu được gửi trong cơ sở dữ liệu mà không sửa đổi và chỉ sử dụng display_address khi tôi muốn một phiên bản hiển thị chuẩn hóa.

Mở để nhận xét/đề xuất.

4

Gần đây tôi đã tạo ra một mô-đun street-address python, và StreetAddressFormatter của nó có thể được sử dụng để bình thường hóa địa chỉ của bạn.

Các vấn đề liên quan