2010-09-21 21 views
25

के लिए एक गैर अनुक्रमिक आईडी/पीके उत्पन्न करना मैं एक नए वेबपैप पर काम शुरू करने के केंद्र में हूं। इसका एक हिस्सा उपयोगकर्ता पेज देगा जो वे एक से कई रिश्ते में अनुकूलित कर सकते हैं। इन पृष्ठों को स्वाभाविक रूप से अद्वितीय यूआरएल होना चाहिए।एक Django मॉडल

अपने डिवाइस पर छोड़ दिया गया, Django सामान्य रूप से एक मॉडल के लिए मानक AUTOINCREMENT आईडी असाइन करेगा। हालांकि यह शानदार रूप से काम करता है, यह बहुत अच्छा नहीं लग रहा है और यह पेजों को बहुत अनुमानित बनाता है (ऐसा कुछ जो इस मामले में वांछित नहीं है)।

1, 2, 3, 4 के बजाय मैं सेट-लम्बाई, यादृच्छिक रूप से जेनरेट किए गए अल्फान्यूमेरिक तार (जैसे h2esj4) चाहता हूं। 36 वर्णों के संभावित सेट के 6 स्पॉट्स को मुझे दो अरब संयोजनों से अधिक देना चाहिए जो इस चरण में पर्याप्त से अधिक होना चाहिए। बेशक अगर मैं इसे बाद में विस्तारित कर सकता हूं, तो यह भी अच्छा होगा।

  1. रैंडम तार कभी कभी उल्लेख बुरे शब्द या अन्य आपत्तिजनक वाक्यांश:

    लेकिन वहाँ दो मुद्दे हैं। क्या उसमें से छेड़छाड़ करने का कोई अच्छा तरीका है? निष्पक्ष होने के लिए मैं शायद एक संख्यात्मक स्ट्रिंग के लिए बस सकता हूं लेकिन इसमें संघर्ष की संभावना पर भारी हिट होती है।

  2. मैं Django (या डेटाबेस) को भारी उठाने के लिए कैसे प्राप्त करूं? मैं इसके बजाय डालने और नहीं तो कुंजी को काम करता हूं (क्योंकि यह एक कुंजी नहीं होगा)। मुझे लगता है कि समेकन के मुद्दे भी जागरूक होने के बावजूद हैं, भले ही दो नए पेज एक ही समय में उत्पन्न हुए हों और दूसरा (सभी बाधाओं के खिलाफ) जादूगर को पहले की तरह पहले की तरह ही कुंजी मिल गई।

मुझे यह नहीं लगता कि यूआरएल शॉर्टनर अपनी आईडी कैसे उत्पन्न करते हैं, यह दस लाख मील से अलग है। यदि एक के लिए एक सभ्य Django कार्यान्वयन है, तो मैं उस से पिगबैक कर सकता था।

+1

एक नोट के रूप में: 'यूआरएल श ऑर्टेनर्स आमतौर पर अनुक्रमिक यूआरएल उत्पन्न करते हैं :)। –

उत्तर

9

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

एक स्लग AA##AA जैसा दिखता है ताकि 52x52x10x10x52x52 = 731,161,600 संयोजन हो। शायद मुझे एक हजार गुना अधिक आवश्यकता होगी और यदि यह कभी भी एक मुद्दा है, तो मैं 52 गुना अधिक संयोजन के लिए एक पत्र जोड़ सकता हूं।

default तर्क का उपयोग इसे काट नहीं देगा क्योंकि अमूर्त मॉडल को बच्चे पर स्लग टकराव की जांच करने की आवश्यकता है। विरासत ऐसा करने का सबसे आसान, संभवतः एकमात्र तरीका था।

from django.db import models 
from django.contrib.auth.models import User 

import string, random 

class SluggedModel(models.Model): 
    slug = models.SlugField(primary_key=True, unique=True, editable=False, blank=True) 

    def save(self, *args, **kwargs): 
     while not self.slug: 
      ret = [] 
      ret.extend(random.sample(string.letters, 2)) 
      ret.extend(random.sample(string.digits, 2)) 
      ret.extend(random.sample(string.letters, 2)) 

      newslug = ''.join(ret) 
      if self.objects.filter(pk=newslug).count(): 
       self.slug = newslug 

     super(SluggedModel, self).save(*args, **kwargs) 

    class Meta: 
     abstract = True 
+1

दिलचस्प। मैंने हाल ही में कुछ पीके के लिए यूयूआईडी पीढ़ी के दृष्टिकोण में जाने का फैसला किया है, लेकिन मैं इसे भी मान सकता हूं। आपका टुकड़ा वास्तव में वैसे ही काम करेगा जैसा मुझे लगता है। केवल 4 लाइनों को प्रतिस्थापित करें जिन्हें आप 'ret' 'ret = uuid.uuid1()' '' –

+0

'जैसी कुछ चीज़ों के साथ बदलते हैं, मैं आपकी विधि का उपयोग करने की कोशिश कर रहा हूं, लेकिन मुझे क्लासनाम उदाहरण त्रुटि के माध्यम से प्रबंधक पहुंच योग्य नहीं है। आपने इसे कैसे दूर किया? – zsquare

+1

यह एक पुराना धागा है, लेकिन किसी भी व्यक्ति के लिए यह एक चीज है जो इस पर ठोकर खाती है और सावधान रहने के लिए MySQL का उपयोग कर रही है कि MySQL स्ट्रिंग मिलान पर असीमित केस असंवेदनशील है, इसलिए "AB12AB" और "ab12ab" की आईडी दोनों पाए जाएंगी जब तक आप केस संवेदनशील संवेदनशील मिलान का उपयोग करने के लिए स्पष्ट रूप से MySQL को नहीं बताते: http://dev.mysql.com/doc/refman/5.0/en/case- संवेदनशीलता।एचटीएमएल – umbrae

4

आपको Python UUID पर देखने की आवश्यकता हो सकती है, यह यादृच्छिक लंबा वर्ण उत्पन्न कर सकता है। लेकिन आप इसे टुकड़ा कर सकते हैं और छोटे अक्षरों के साथ इच्छित पात्रों की संख्या का उपयोग कर सकते हैं यह सुनिश्चित करने के लिए कि यह टुकड़ा करने के बाद भी अद्वितीय है।

UUIDField स्निपेट आपकी मदद कर सकता है यदि आप स्वयं को यूयूआईडी उत्पन्न करने का दर्द नहीं लेना चाहते हैं।

इसके अलावा प्राप्त करने के लिए आप क्या चाहते हैं यह blog post

+0

यह वास्तव में प्रश्न में हाइलाइट किए गए दो मुद्दों में से किसी एक को बाधित नहीं करता है। अनुमोदित 'UUIDField' मेरे मॉडल से दूर कुछ कोड को अमूर्त करने में मदद करता है लेकिन यह अभी भी डेटाबेस के बाहर है (जहां मुझे यह वास्तव में पसंद आएगा) और अभी भी कठोर शब्दों को वर्तनी करने में सक्षम है। – Oli

20

वहाँ में निर्मित Django तरीका है पर एक नजर है। primary_key=True और कुंजी पीढ़ी समारोह के default= नाम के साथ "कस्टम पेज" के मॉडल के लिए एक फ़ील्ड जोड़ें, इस तरह: हर मॉडल उदाहरण page के लिए

class CustomPage(models.Model): 
    ... 
    mykey = models.CharField(max_length=6, primary_key=True, default=pkgen) 
    ... 

अब, page.pkpage.mykey के लिए एक उपनाम है, जो स्वत: किया जा रहा है हो जाता है उस उदाहरण के निर्माण के समय आपके फ़ंक्शन pkgen() द्वारा लौटाई गई स्ट्रिंग के साथ असाइन किया गया।
फास्ट & गंदा कार्यान्वयन: (यह मानते हुए random() पर्याप्त यादृच्छिक है)

def pkgen(): 
    from base64 import b32encode 
    from hashlib import sha1 
    from random import random 
    rude = ('lol',) 
    bad_pk = True 
    while bad_pk: 
     pk = b32encode(sha1(str(random())).digest()).lower()[:6] 
     bad_pk = False 
     for rw in rude: 
      if pk.find(rw) >= 0: bad_pk = True 
    return pk 

दो पृष्ठों समान प्राथमिक कुंजी प्राप्त होने की संभाव्यता बहुत कम है, और वहाँ कोई संगामिति मुद्दे हैं। और, couse के, एन्कोडेड स्ट्रिंग से अधिक वर्णों को टुकड़ा करके यह विधि आसानी से एक्स्टेंसिबल है।

+3

मुझे इस अवधारणा में b32encode और sha1 के बिंदु को समझ में नहीं आता है। वर्णों की एक सूची की एक साधारण यादृच्छिक पसंद नहीं है, परिणामस्वरूप यादृच्छिक परिणाम उत्पन्न होता है, बहुत कम ओवरहेड (और कोड) के साथ? – Oli

+0

@ ओली आप अपनी इच्छित स्ट्रिंग जेनरेट कर सकते हैं, बिंदु यह है कि डिफ़ॉल्ट रूप से कॉल बैक फ़ंक्शन सेट करना वह तरीका है जिसे आप स्ट्रिंग को पीके के रूप में असाइन करेंगे। मुझे सही समाधान की तरह लगता है +1 अपवोट – Rasiel

+1

एक पुन: प्रयोज्य सेटिंग में, यह टक्कर जांच नहीं कर सकता है। एक ही स्लग के साथ एक मॉडल के एक से अधिक उदाहरण नहीं हो सकता है। यह 'डिफ़ॉल्ट' तर्क में एक दोष है जो अतिरिक्त जानकारी लेने में सक्षम नहीं है (जनरेटर को कक्षा पास करने के लिए)। – Oli

1

ओली: आप अशिष्ट शब्द वर्तनी, आप हमेशा तुलना कर सकते हैं/उनके लिए अपने UUIDField खोज, Django गालियां बकने की क्रिया फिल्टर का उपयोग कर, और किसी भी UUIDs कि triggery हो सकता है छोड़ बारे में चिंतित हैं।

0

यही वह है जो मैंने यूयूआईडी का उपयोग करके समाप्त किया।

import uuid 

from django.db import models 
from django.contrib.auth.models import User 


class SluggedModel(models.Model): 
    slug = models.SlugField(primary_key=True, unique=True, editable=False, blank=True) 

    def save(self, *args, **kwargs): 
     if not self.slug: 
      uuid.uuid4().hex[:16] # can vary up to 32 chars in length 
     super(SluggedModel, self).save(*args, **kwargs) 

    class Meta: 
     abstract = True 
2

Django अब एक UUIDField type भी शामिल है, तो आप किसी भी कस्टम कोड या बाहरी पैकेज श्रीकांत Chundi सुझाव जरूरत नहीं है। इस कार्यान्वयन डैश से हेक्स तार का उपयोग करता है, तो पाठ 1337 भाव abad1d3a :) तरह से बच्चों के सुरक्षित, अन्य सुंदर है

आप इसे एक प्राथमिक कुंजी के रूप uuid क्षेत्र के रूप में नामित pk को इस तरह का प्रयोग करेंगे:

import uuid 
from django.db import models 

class MyModel(models.Model): 
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) 
    # other fields 

ध्यान दें, तथापि, जब आप इस दृष्टिकोण के मार्ग रहे urls.py में, आप mentioned here रूप में एक अलग regex, जैसे कि जरूरत:

urlpatterns = [ 
    url(r'mymodel/(?P<pk>[^/]+)/$', MyModelDetailView.as_view(), 
     name='mymodel'), 
] 
+0

में उस उत्तर पर मेरी टिप्पणी भी यहां है। यूयूआईडी अद्वितीय, निकट अनंत आईडी के लिए बहुत अच्छे हैं लेकिन वे बहुत उपयोगकर्ता हैं-असभ्य हैं। डीजेगो और वेब के संदर्भ में विचार करें- यह ऐसा कुछ है जो * प्रदर्शन पर होगा * * मैन्युअल रूप से लिखित हो सकता है, और यादृच्छिक तार अंततः कसम खाता है। – Oli

+0

हेक्साडेसिमल संख्या प्रणाली में आप किस कसम शब्द का उच्चारण कर सकते हैं? ध्यान दें केवल उपलब्ध अक्षर ए, बी, सी, डी, ई, एफ हैं। मैं मानता हूं कि यादृच्छिक लम्बी तार शायद हर उपयोग के मामले के अनुरूप नहीं हो सकती है। – metakermit

+1

आपने यह पूछा: 'B00B5' .. लेकिन हाँ, हेक्स निश्चित रूप से बेहतर है। यहां 36-चार लंबाई की वास्तविक समस्या असली समस्या है। – Oli

संबंधित मुद्दे