জ্যাঙ্গো মডেলগুলিতে একটি প্রাথমিক কী হিসাবে একটি ইউইউডি ব্যবহার করা (জেনেরিক সম্পর্কের প্রভাব)


91

বিভিন্ন কারণে ^, আমি আমার কিছু জ্যাঙ্গো মডেলগুলিতে একটি ইউইউডি একটি প্রাথমিক কী হিসাবে ব্যবহার করতে চাই। যদি আমি এটি করি তবে আমি কী এখনও কন্টেন্টটাইপের মাধ্যমে জেনেরিক সম্পর্ক ব্যবহার করে "অবদান.কমেন্টস", "জাঙ্গো-ভোটদান" বা "জ্যাঙ্গো-ট্যাগিং" এর মতো বাইরের অ্যাপ্লিকেশনগুলি ব্যবহার করতে সক্ষম হব?

উদাহরণস্বরূপ "জাঙ্গো-ভোটদান" ব্যবহার করে ভোটের মডেলটি দেখতে এমন দেখাচ্ছে:

class Vote(models.Model):
    user         = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id    = models.PositiveIntegerField()
    object       = generic.GenericForeignKey('content_type', 'object_id')
    vote         = models.SmallIntegerField(choices=SCORES)

এই অ্যাপ্লিকেশনটি ধরে নিয়েছে বলে মনে হচ্ছে যে মডেলটিতে ভোট দেওয়া হচ্ছে তার জন্য প্রাথমিক কীটি একটি পূর্ণসংখ্যা।

অন্তর্নির্মিত মন্তব্য অ্যাপ্লিকেশনটি অ-পূর্ণসংখ্যা পিকেগুলিকে পরিচালনা করতে সক্ষম বলে মনে হচ্ছে, যদিও:

class BaseCommentAbstractModel(models.Model):
    content_type   = models.ForeignKey(ContentType,
            verbose_name=_('content type'),
            related_name="content_type_set_for_%(class)s")
    object_pk      = models.TextField(_('object ID'))
    content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")

এই "পূর্ণসংখ্যা-পিকে-ধরে নেওয়া" সমস্যাটি কি তৃতীয় পক্ষের অ্যাপ্লিকেশনগুলির জন্য একটি সাধারণ পরিস্থিতি যা ইউইউডিগুলি ব্যবহার করে ব্যথা করে? বা, সম্ভবত, আমি এই পরিস্থিতিটি ভুলভাবে লিখছি?

খুব বেশি ঝামেলা না করে জ্যাঙ্গোতে কি ইউআইডিগুলিকে প্রাথমিক কী হিসাবে ব্যবহার করার কোনও উপায় আছে?


^ কয়েকটি কারণ: অবজেক্টের গণনা গোপন করা, ইউআরএল "আইডি ক্রলিং" রোধ করা, বিরোধী অবজেক্ট তৈরি করতে একাধিক সার্ভার ব্যবহার করে, ...

উত্তর:


56

একটি ইউইউডি প্রাথমিক কী কেবল জেনেরিক সম্পর্কের ক্ষেত্রেই নয়, সাধারণভাবে দক্ষতার সাথেও সমস্যা সৃষ্টি করবে: প্রতিটি বিদেশী কী উল্লেখযোগ্যভাবে ব্যয়বহুল — উভয়ই সংরক্ষণ এবং মেশিনের শব্দের চেয়ে যোগ দিতে join

যাইহোক, কোনও কিছুরই জন্য ইউইউডিউর প্রাথমিক কী হওয়া দরকার: কেবলমাত্র এটির একটি গৌণ কী তৈরি করুন, সাথে একটি uuid ক্ষেত্রের সাথে আপনার মডেল পরিপূরক করুন unique=True। অন্তর্নিহিত প্রাথমিক কীটি স্বাভাবিক হিসাবে (আপনার সিস্টেমে অভ্যন্তরীণ) ব্যবহার করুন এবং আপনার বাহ্যিক শনাক্তকারী হিসাবে ইউইউডি ব্যবহার করুন।


16
জো হোলোয়, এর দরকার নেই: আপনি কেবল ক্ষেত্রের হিসাবে ইউইউডি প্রজন্মের ফাংশন সরবরাহ করতে পারেন default
পাই ডিলপোর্ট

4
জো: আমি আমার মডেলটিতে আমার ইউআইডিগুলি তৈরি করতে আমি জাঙ্গো_ এক্সটেনশনস.ডিবি.ফিল্ডস.উইউইডি ফিল্ড ব্যবহার করি। এটি সহজ, আমি ঠিক এইভাবে আমার ক্ষেত্রটি সংজ্ঞায়িত করেছি: user_uuid = UIDField ()
মিচফ

4
django_extensions.db.fields.UUIDField@ ম্যাথেজচিনকেল : আপনি যখন মিচফ দ্বারা উল্লিখিত হিসাবে ব্যবহার করেন, জ্যাঙ্গো-দক্ষিণ অভিবাসন নিয়ে আপনার কোনও সমস্যা হবে না - তাঁর উল্লেখ করা ক্ষেত্রটি দক্ষিণ অভিবাসনের জন্য অন্তর্নির্মিত সমর্থন করেছে।
টেডেক

126
ভয়াবহ উত্তর। পোস্টগ্রিসের নেটিভ (128 বিট) ইউআইডি রয়েছে যা একটি 64 বিট মেশিনে মাত্র 2 টি শব্দ, তাই দেশীয় bit৪ বিট আইএনটির চেয়ে "উল্লেখযোগ্যভাবে বেশি ব্যয়বহুল" হবে না not
পোস্টফিউচারিস্ট

8
পিট, এটির উপর একটি বিটি্রি সূচক রয়েছে তা প্রদত্ত, একটি প্রদত্ত ক্যোয়ারীতে কতটি তুলনা রয়েছে? বেশি না. এছাড়াও, আমি নিশ্চিত যে মেমক্যাম্প কলটি বেশিরভাগ ওএসে প্রান্তিককরণ এবং অনুকূলিত হবে। প্রশ্নের প্রকৃতির ভিত্তিতে আমি বলব যে সম্ভাব্য (সম্ভবত তুচ্ছ) পারফরম্যান্স পার্থক্যের কারণে ইউইউডি না ব্যবহার করা ভুল অপটিমাইজেশন।
পোস্টফিউচারিস্ট

219

ডকুমেন্টেশনে যেমন দেখা গেছে , জাজানো ১.৮ থেকে ইউইউডি ফিল্ডে একটি বিল্ট রয়েছে। কোনও ইউইউডি বনাম পূর্ণসংখ্যার ব্যবহারের সময় পারফরম্যান্সের পার্থক্য নগণ্য।

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

আরও তথ্যের জন্য আপনি এই উত্তরটিও পরীক্ষা করতে পারেন ।


@ কীথ্যাকবার্থ টেবিলের জন্য স্বয়ংক্রিয়ভাবে আইডি তৈরি করার সময় আমরা কীভাবে এটি প্রতিবার ব্যবহার করতে জ্যাঙ্গো সেট করব?
anon58192932

4
@ anon58192932 "প্রতিবার" দ্বারা আপনি ঠিক কী বোঝাতে চেয়েছেন তা সত্য নয়। আপনি যদি প্রতিটি মডেলের জন্য ইউআইডিগুলি ব্যবহার করতে চান তবে নিজের অ্যাবস্ট্রাক্ট বেস মডেল তৈরি করুন এবং এটি জ্যাঙ্গো.মোডেলস.মোডেলের পরিবর্তে ব্যবহার করুন।
31 16

4
অন্তর্নিহিত ডাটাবেসটি ইউইউডি টাইপ সমর্থন করলে পারফরম্যান্স পার্থক্য কেবল নগন্য। জ্যাঙ্গো এখনও বেশিরভাগ ডিবি-র জন্য একটি চার্ফিল্ড ব্যবহার করে (ইউইউডি ক্ষেত্রটি সমর্থন করার জন্য পোস্টগ্রেস্কেল একমাত্র ডকুমেন্টেড ডিবি)।
নির্ঝর

আমি কেন বিভ্রান্ত কারণ এটি একটি জনপ্রিয় উত্তর ... প্রশ্নটি তৃতীয় পক্ষের প্যাকেজগুলির সাথে অসুবিধা সম্পর্কে জিজ্ঞাসা করছিল। জ্যাঙ্গো স্থানীয়ভাবে ইউইউডি সমর্থন করে সত্ত্বেও, এখনও অনেকগুলি প্যাকেজ রয়েছে যা ইউইউডিগুলিতে অ্যাকাউন্ট করে না। আমার অভিজ্ঞতায়, এটি একটি ব্যথা।
ambe5960

12

আমি একই অবস্থা গাড়ীতে আঘাত এবং খুঁজে পাওয়া যায় নি কর্মকর্তা জ্যাঙ্গো ডকুমেন্টেশন , যে object_idহিসাবে একই ধরনের হতে হবে তা নয় primary_key সংশ্লিষ্ট মডেল। উদাহরণস্বরূপ, আপনি যদি চান যে আপনার জেনেরিক সম্পর্কটি ইন্টিজারফিল্ড এবং চারফিল্ড আইডির উভয়ের জন্যই বৈধ হতে পারে তবে কেবল আপনার object_idএকটি চারফিল্ড হিসাবে সেট করুন । যেহেতু পূর্ণসংখ্যার স্ট্রিংগুলিতে জোর করা যায় এটি ভাল হবে। একইভাবে ইউআইডিফিল্ডের জন্য যায় ।

উদাহরণ:

class Vote(models.Model):
    user         = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id    = models.CharField(max_length=50) # <<-- This line was modified 
    object       = generic.GenericForeignKey('content_type', 'object_id')
    vote         = models.SmallIntegerField(choices=SCORES)

4

ইউকেউডিকে পিকে হিসাবে আসল সমস্যাটি হ'ল ডিস্ক বিভাজন এবং অ-সংখ্যাসূচক শনাক্তকারীদের সাথে যুক্ত অবক্ষয় সন্নিবেশ। কারণ পিকে একটি ক্লাস্টার্ড সূচক, যখন এটি স্বয়ং-বর্ধিত হয় না, আপনার ডিবি ইঞ্জিনটিকে নিম্ন সীমাবদ্ধতার আইডি সহ একটি সারি সন্নিবেশ করার সময় আপনার শারীরিক ড্রাইভটি রিসর্ট করতে হবে, যা ইউইউডিগুলির সাথে সর্বদা ঘটবে। আপনি যখন আপনার ডিবিতে প্রচুর ডেটা পাবেন, একটি নতুন রেকর্ড সন্নিবেশ করতে এটি বেশ কয়েক সেকেন্ড বা এমনকি কয়েক মিনিট সময় নিতে পারে। এবং আপনার ডিস্ক অবশেষে খণ্ডিত হয়ে উঠবে, পর্যায়ক্রমিক ডিস্ক ডিফ্র্যাগমেন্টেশন প্রয়োজন। এই সব সত্যিই খারাপ।

এগুলির সমাধান করার জন্য, আমি সম্প্রতি নীচের আর্কিটেকচারটি নিয়ে এসেছি যা ভেবেছিলাম ভাগ করার উপযুক্ত।

ইউআইডিউড সিউডো-প্রাথমিক-কী

এই পদ্ধতিটি আপনাকে কোনও ইউইউডি-র প্রাথমিক কী (কোনও অনন্য সূচক ইউআইউডি ব্যবহার করে) হিসাবে বেনিফিট অর্জন করার অনুমতি দেয়, বিভাজনকে মোকাবেলা করার জন্য একটি স্বয়ং-বর্ধিত পিকে বজায় রাখার সময় এবং কোনও অ-সংখ্যাযুক্ত পিকে থাকার কর্মক্ষমতা হ্রাসের উদ্বেগ সন্নিবেশ করে।

কিভাবে এটা কাজ করে:

  1. pkidআপনার ডিবি মডেলগুলিতে কল হওয়া একটি স্ব-বর্ধিত প্রাথমিক কী তৈরি করুন।
  2. idসংখ্যার প্রাথমিক কী-এর পরিবর্তে আপনাকে কোনও ইউইউডি আইডি দিয়ে অনুসন্ধান করার অনুমতি দেওয়ার জন্য একটি অনন্য-সূচকযুক্ত ইউআইডি ফিল্ড যুক্ত করুন।
  3. to_field='id'আপনার বিদেশী-কীগুলি সংখ্যাসূচক আইডির পরিবর্তে সিউডো-পিকে যথাযথভাবে উপস্থাপন করতে অনুমতি দেওয়ার জন্য ইউএনইউডিতে (ব্যবহার করে ) ফরেনকি কে নির্দেশ করুন।

মূলত, আপনি নিম্নলিখিতগুলি করবেন:

প্রথমে একটি বিমূর্ত জ্যাঙ্গো বেস মডেল তৈরি করুন

class UUIDModel(models.Model):
    pkid = models.BigAutoField(primary_key=True, editable=False)
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)

    class Meta:
        abstract = True

মডেলগুলির পরিবর্তে বেস মডেলটি বাড়ানো নিশ্চিত করুন Make মডেল

class Site(UUIDModel):
    name = models.CharField(max_length=255)

এছাড়াও নিশ্চিত করুন যে আপনার ফরেনকিগুলি idঅটো-বর্ধিত pkidক্ষেত্রের পরিবর্তে ইউইউডি ফিল্ডের দিকে নির্দেশ করছে :

class Page(UUIDModel):
    site = models.ForeignKey(Site, to_field='id', on_delete=models.CASCADE)

আপনি যদি জ্যাঙ্গো রেস্ট ফ্রেমওয়ার্ক (ডিআরএফ) ব্যবহার করছেন তবে ডিফল্ট অনুসন্ধানের ক্ষেত্রটি সেট করতে একটি বেস ভিউসেট শ্রেণি তৈরি করা নিশ্চিত করে নিন:

class UUIDModelViewSet(viewsets.ModelViewSet):
    lookup_field = 'id' 

আপনার এপিআই ভিউগুলির জন্য বেস মডেলভিউসেটের পরিবর্তে এটি প্রসারিত করুন:

class SiteViewSet(UUIDModelViewSet):
    model = Site

class PageViewSet(UUIDModelViewSet):
    model = Page

কেন এবং কীভাবে এই নিবন্ধে আরও নোট: https://www.stevenmoseley.com/blog/uuid-primary-keys-django-rest-framework-2- পদক্ষেপ


0

নিম্নলিখিত পদক্ষেপগুলি ব্যবহার করে এটি একটি কাস্টম বেস বিমূর্ত মডেল ব্যবহার করে করা যেতে পারে।

প্রথমে আপনার প্রকল্পে একটি ফোল্ডার তৈরি করুন একে বেসমডেল বলে তারপরে নীচের সাথে একটি বিমূর্ত মডেলবেস.পি যুক্ত করুন:

from django.db import models
import uuid


class BaseAbstractModel(models.Model):

    """
     This model defines base models that implements common fields like:
     created_at
     updated_at
     is_deleted
    """
    id=models.UUIDField(primary_key=True, ,unique=True,default=uuid.uuid4, editable=False)
    created_at=models.DateTimeField(auto_now_add=True,editable=False)
    updated_at=models.DateTimeField(auto_now=True,editable=False)
    is_deleted=models.BooleanField(default=False)

    def soft_delete(self):
        """soft  delete a model instance"""
        self.is_deleted=True
        self.save()

    class Meta:
        abstract=True
        ordering=['-created_at']

দ্বিতীয়: প্রতিটি অ্যাপ্লিকেশানের জন্য আপনার সমস্ত মডেল ফাইলটিতে এটি করুন

from django.db import models
from basemodel import BaseAbstractModel
import uuid

# Create your models here.

class Incident(BaseAbstractModel):

    """ Incident model  """

    place = models.CharField(max_length=50,blank=False, null=False)
    personal_number = models.CharField(max_length=12,blank=False, null=False)
    description = models.TextField(max_length=500,blank=False, null=False)
    action = models.TextField(max_length=500,blank=True, null=True)
    image = models.ImageField(upload_to='images/',blank=True, null=True)
    incident_date=models.DateTimeField(blank=False, null=False) 

সুতরাং উপরের মডেল ঘটনাটি বেসাবস্ট্রাক্ট মডেলের সমস্ত ক্ষেত্র সহজাত।


-1

"পুনরায় জবাব দেওয়া যায় কারণ" জ্যাঙ্গোকে কোনও অটো-বর্ধিত পূর্ণসংখ্যার পরিবর্তে সমস্ত টেবিলের সমস্ত ডাটাবেস আইডির জন্য একটি ইউআইডি ব্যবহার করার উপায় আছে? "

অবশ্যই, আমি এটি করতে পারি:

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

আমার সমস্ত সারণীতে, তবে আমি এটি করার কোনও উপায় খুঁজে পাচ্ছি না:

  1. তৃতীয় পক্ষের মডিউল
  2. জ্যাঙ্গো ম্যান্টিটোম্যান টেবিল তৈরি করেছে

সুতরাং, এটি একটি নিখোঁজ জ্যাঙ্গো বৈশিষ্ট্য বলে মনে হচ্ছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.