2 ক্ষেত্রের উপর একটি অনন্য আইডি তৈরি করার কোনও উপায় আছে?


14

এখানে আমার মডেল:

class GroupedModels(models.Model):
    other_model_one = models.ForeignKey('app.other_model')
    other_model_two = models.ForeignKey('app.other_model')

মূলত, আমি যা চাই তা other_modelএই টেবিলটিতে অনন্য হওয়ার জন্য । এর অর্থ হ'ল যদি সেখানে other_model_oneআইডি রয়েছে এমন কোনও রেকর্ড থাকলে 123আমার আর কোনও রেকর্ড other_model_twoআইডি দিয়ে তৈরি করার অনুমতি দেওয়া উচিত নয় 123। আমি cleanঅনুমান করে ওভাররাইড করতে পারি তবে আমি ভাবছিলাম যে জ্যাঙ্গোতে কোনও বিল্ট রয়েছে।

আমি পিএসকিউএল সহ 2.2.5 সংস্করণ ব্যবহার করছি।

সম্পাদনা করুন: এটি একযোগে পরিস্থিতি নয়। যদি আমি সঙ্গে একটি রেকর্ড যোগ other_model_one_id=1অপরের এবং other_model_two_id=2, আমি সাথে অন্য রেকর্ড যোগ করতে সক্ষম হবে না other_model_one_id=2এবং অন্যান্যother_model_two_id=1


আপনি জ্যাঙ্গো সংস্করণটি কী ব্যবহার করছেন?
উইলেম ভ্যান অনসেম

আমি সংস্করণ 2.2.5 ব্যবহার করছি
পিটফল 17


1
এটি একসাথে এক অনন্য পরিস্থিতি নয়, এটি অনন্য তবে 2 ক্ষেত্রেরও বেশি এটি যদি কোনও ধারণা দেয়।
পিটফল 17

উত্তর:


10

আমি এখানে বেশ কয়েকটি বিকল্প ব্যাখ্যা করছি, সম্ভবত তাদের মধ্যে একটি বা সংমিশ্রণটি আপনার পক্ষে কার্যকর হতে পারে।

উপেক্ষা করা save

আপনার সীমাবদ্ধতা একটি ব্যবসায়িক নিয়ম, আপনি saveডেটা ধারাবাহিক রাখতে পদ্ধতিটি ওভাররাইড করতে পারেন :


class GroupedModels(models.Model): 
    # ...
    def clean(self):
        if (self.other_model_one.pk == self.other_model_two.pk):
            raise ValidationError({'other_model_one':'Some message'}) 
        if (self.other_model_one.pk < self.other_model_two.pk):
            #switching models
            self.other_model_one, self.other_model_two = self.other_model_two, self.other_model_one
    # ...
    def save(self, *args, **kwargs):
        self.clean()
        super(GroupedModels, self).save(*args, **kwargs)

পরিবর্তন নকশা

আমি বুঝতে সহজ একটি নমুনা রেখেছি। ধরা যাক এই দৃশ্যটি:

class BasketballMatch(models.Model):
    local = models.ForeignKey('app.team')
    visitor = models.ForeignKey('app.team')

এখন, আপনি কোনও দলকে নিজের সাথে ম্যাচ খেলতে এড়াতে চান টিম এ শুধুমাত্র একবার বি বিয়ের সাথে খেলতে পারে (প্রায় আপনার নিয়ম)। আপনি আপনার মডেলগুলি আবার ডিজাইন করতে পারেন:

class BasketballMatch(models.Model):
    HOME = 'H'
    GUEST = 'G'
    ROLES = [
        (HOME, 'Home'),
        (GUEST, 'Guest'),
    ]
    match_id = models.IntegerField()
    role = models.CharField(max_length=1, choices=ROLES)
    player = models.ForeignKey('app.other_model')

    class Meta:
      unique_together = [ ( 'match_id', 'role', ) ,
                          ( 'match_id', 'player',) , ]

ManyToManyField.symmetrical

এটি দেখতে একটি প্রতিসম ইস্যুর মতো, জ্যাঙ্গো এটি আপনার পক্ষে পরিচালনা করতে পারে। GroupedModelsমডেল তৈরি করার পরিবর্তে , কেবল নিজের সাথে একটি ম্যান্টি টোমনিফিল্ড ফিল্ড তৈরি করুন OtherModel:

from django.db import models
class OtherModel(models.Model):
    ...
    grouped_models = models.ManyToManyField("self")

এই পরিস্থিতিগুলির জন্য জাজানো এটি তৈরি করেছে।


পদ্ধতির একটি হ'ল আমি ব্যবহার করছি (তবে একটি ডাটাবেসের সীমাবদ্ধতার জন্য আশা করছি)। আমার দৃশ্যে অ্যাপ্রোচ 2 কিছুটা আলাদা, আমি এপ্রোচ 3 ব্যবহার করিনি কারণ গ্রুপিংয়ে আরও বেশি ডেটা সঞ্চয় করতে চেয়েছিলাম। উত্তরের জন্য ধন্যবাদ.
পিটফল

যদি কোনও দল একটি গেম খেলে থাকে তবে তারা আর কখনও গেম খেলতে পারে না। কারণ আমি match_idদলগুলিকে সীমাহীন ম্যাচ খেলতে দেওয়ার জন্য, অকেজো বাধাতে অন্তর্ভুক্ত করেছি । খেলাকে আবার সীমাবদ্ধ করতে কেবল এই ক্ষেত্রটি সরিয়ে দিন।
দানি হেরের

অই হ্যাঁ! আপনাকে ধন্যবাদ আমি এটি মিস করেছি এবং আমার অন্যান্য মডেলটি এক থেকে এক ক্ষেত্রে হতে পারে।
পিটফল

1
আমার মনে হয় আমি 2 নম্বর অপশনটি পছন্দ করি। এটির সাথে আমার একমাত্র সমস্যাটি হ'ল এটির পক্ষে যুক্তিযুক্তভাবে "গড়" ব্যবহারকারীর জন্য একটি কাস্টম ফর্ম প্রয়োজন, এমন একটি বিশ্বে যেখানে প্রশাসকটি এফই হিসাবে ব্যবহৃত হয়। দুর্ভাগ্যক্রমে, আমি সেই পৃথিবীতে বাস করি। তবে আমি মনে করি এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। ধন্যবাদ!
পিটফল

দ্বিতীয় বিকল্পটি হ'ল উপায়। এটি একটি দুর্দান্ত উত্তর। অ্যাডমিন সম্পর্কিত @ সমস্যার বিষয়ে আমি আরও উত্তর যুক্ত করেছি। অ্যাডমিন ফর্মটি সমাধান করার জন্য কোনও বড় সমস্যা হওয়া উচিত নয়।
সেজার

1

এটি খুব সন্তোষজনক উত্তর নয়, তবে দুর্ভাগ্যক্রমে সত্যটি হ'ল আপনি যা সাধারণ বিল্ট-ইন বৈশিষ্ট্যটির সাথে বর্ণনা করছেন তা করার কোনও উপায় নেই।

আপনি যা বর্ণনা করেছেন cleanতা কার্যকর হবে তবে আপনাকে ম্যানুয়ালি কল করতে সতর্ক থাকতে হবে কারণ আমি মনে করি মডেলফর্ম ব্যবহার করার সময় এটি কেবল স্বয়ংক্রিয়ভাবে বলা হয়েছিল। আপনি একটি জটিল ডাটাবেস সীমাবদ্ধতা তৈরি করতে সক্ষম হতে পারেন তবে এটি জ্যাঙ্গোর বাইরে থাকতে পারে এবং আপনাকে ডাটাবেস ব্যতিক্রমগুলি পরিচালনা করতে হবে (লেনদেনের মাঝামাঝি সময়ে জাঙ্গোতে এটি কঠিন হতে পারে)।

ডেটা গঠনের আরও ভাল উপায় আছে?


হ্যাঁ, আপনি ঠিক বলেছেন যে এটি ম্যানুয়ালি কল করতে হয়েছে যার কারণে আমি পদ্ধতির পছন্দ করি না। এটি যেমন অ্যাডমিনে আমি চাই তেমনই কাজ করে, যেমনটি আপনি উল্লেখ করেছেন।
পিটফল

0

ইতিমধ্যে একটি মহান উত্তর থেকে দানি Herrera তবে আমি আরো এটিতে সম্প্রসারিত করতে ইচ্ছুক।

দ্বিতীয় বিকল্পটিতে যেমন ব্যাখ্যা করা হয়েছে, ওপি দ্বারা প্রয়োজনীয় সমাধানটি হ'ল নকশা পরিবর্তন করা এবং যুগলভাবে দুটি অনন্য বাধা প্রয়োগ করা। বাস্কেটবল ম্যাচগুলির সাথে সাদৃশ্যটি সমস্যাটিকে খুব ব্যবহারিক উপায়ে চিত্রিত করে।

বাস্কেটবল ম্যাচের পরিবর্তে, আমি ফুটবল (বা সকার) গেমের সাথে উদাহরণ ব্যবহার করি। একটি ফুটবল খেলা (যা আমি এটি বলি Event) দুটি দল খেলে (আমার মডেলগুলিতে একটি দল হয় Competitor)। এটি একটি বহু থেকে বহু সম্পর্ক ( m:n), nএই বিশেষ ক্ষেত্রে দুটি সীমাবদ্ধ সহ , নীতিটি সীমাহীন সংখ্যার জন্য উপযুক্ত।

আমাদের মডেলগুলি দেখতে এখানে:

class Competitor(models.Model):
    name = models.CharField(max_length=100)
    city = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Event(models.Model):
    title = models.CharField(max_length=200)
    venue = models.CharField(max_length=100)
    time = models.DateTimeField()
    participants = models.ManyToManyField(Competitor)

    def __str__(self):
        return self.title

একটি ইভেন্ট হতে পারে:

  • শিরোনাম: কারাবাও কাপ, চতুর্থ রাউন্ড,
  • ভেন্যু: অ্যানফিল্ড
  • সময়: 30. অক্টোবর 2019, 19:30 GMT
  • অংশগ্রহণকারীদের:
    • নাম: লিভারপুল, শহর: লিভারপুল
    • নাম: আর্সেনাল, শহর: লন্ডন

এখন আমাদের প্রশ্ন থেকে সমস্যাটি সমাধান করতে হবে। জ্যাঙ্গো স্বয়ংক্রিয়ভাবে অনেকগুলি থেকে বহু সম্পর্কযুক্ত মডেলগুলির মধ্যে একটি মধ্যবর্তী টেবিল তৈরি করে, তবে আমরা একটি কাস্টম মডেল ব্যবহার করতে পারি এবং আরও ক্ষেত্রগুলি যুক্ত করতে পারি। আমি যে মডেল কল Participant:

ক্লাস অংশগ্রহণকারী (মডেল। মডেল):
    ভূমিকা = (
        ('এইচ', 'হোম'),
        ('ভি', 'দর্শনার্থী'),
    )
    ইভেন্ট = মডেলগুলি ore ফোরইনকি (ইভেন্ট, অন_ডিলিট = মডেল AS ক্যাসকেড)
    প্রতিযোগী = মডেলগুলি ore
    ভূমিকা = মডেলস.চারফিল্ড (সর্বোচ্চ_ দৈর্ঘ্য = 1, পছন্দগুলি = ROLES)

    ক্লাস মেটা:
        অনন্য_ একসাথে = (
            ('ইভেন্ট', 'ভূমিকা'),
            ('ইভেন্ট', 'প্রতিযোগী'),
        )

    Def_____ __ (স্ব):
        '{} - {}'। ফর্ম্যাট (স্ব।

ManyToManyFieldএকটি বিকল্প আছে throughযা আমাদের অন্তর্বর্তী মডেল নির্দিষ্ট করার অনুমতি দেয়। মডেলটিতে এটি পরিবর্তন করা যাক Event:

class Event(models.Model):
    title = models.CharField(max_length=200)
    venue = models.CharField(max_length=100)
    time = models.DateTimeField()
    participants = models.ManyToManyField(
        Competitor,
        related_name='events', # if we want to retrieve events for a competitor
        through='Participant'
    )

    def __str__(self):
        return self.title

অনন্য প্রতিবন্ধকতা এখন স্বয়ংক্রিয়ভাবে প্রতি ইভেন্ট প্রতিযোগীদের সংখ্যা দু'জনের মধ্যে সীমাবদ্ধ করবে (কারণ কেবলমাত্র দুটি ভূমিকা রয়েছে: হোম এবং দর্শনার্থী )।

একটি নির্দিষ্ট ইভেন্টে (ফুটবল খেলা) কেবলমাত্র একটি হোম দল এবং কেবলমাত্র একটি দর্শনার্থী দল থাকতে পারে। একটি ক্লাব ( Competitor) হোম দল হিসাবে বা দর্শনার্থী দল হিসাবে উপস্থিত হতে পারে।

অ্যাডমিনে আমরা এখন কীভাবে এই সমস্ত জিনিস পরিচালনা করব? এটার মত:

from django.contrib import admin

from .models import Competitor, Event, Participant


class ParticipantInline(admin.StackedInline): # or admin.TabularInline
    model = Participant
    max_num = 2


class CompetitorAdmin(admin.ModelAdmin):
    fields = ('name', 'city',)


class EventAdmin(admin.ModelAdmin):
    fields = ('title', 'venue', 'time',)
    inlines = [ParticipantInline]


admin.site.register(Competitor, CompetitorAdmin)
admin.site.register(Event, EventAdmin)

আমরা Participantইনলাইন হিসাবে যুক্ত করেছি EventAdmin। আমরা যখন নতুন তৈরি করি তখন আমরা Eventহোম দল এবং দর্শনার্থী দলকে বেছে নিতে পারি। বিকল্পটি max_numপ্রবেশের সংখ্যা 2-এর মধ্যে সীমাবদ্ধ করে, সুতরাং ইভেন্টে আরও 2 টি দল যুক্ত করা যাবে না।

এটি কোনও ভিন্ন ব্যবহারের ক্ষেত্রে রিফ্যাক্টর করা যেতে পারে। আসুন আমাদের ঘটনা সুইমিং প্রতিযোগিতায় এবং পরিবর্তে বাড়ি এবং পরিদর্শক, আমরা রাস্তা 1 8. করতে আমরা শুধু refactor আছে বলতে দাও Participant:

class Participant(models.Model):
    ROLES = (
        ('L1', 'lane 1'),
        ('L2', 'lane 2'),
        # ... L3 to L8
    )
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    competitor = models.ForeignKey(Competitor, on_delete=models.CASCADE)
    role = models.CharField(max_length=1, choices=ROLES)

    class Meta:
        unique_together = (
            ('event', 'role'),
            ('event', 'competitor'),
        )

    def __str__(self):
        return '{} - {}'.format(self.event, self.get_role_display())

এই পরিবর্তনটি সহ আমাদের এই ইভেন্টটি থাকতে পারে:

  • শিরোনাম: এফআইএনএ 2019, 50 মিটার ব্যাকস্ট্রোক পুরুষদের ফাইনাল,

    • ভেন্যু: নাম্বু বিশ্ববিদ্যালয় পৌরসভা অ্যাকোয়াটিক্স কেন্দ্র
    • সময়: 28. জুলাই 2019, 20:02 ইউটিসি + 9
    • অংশগ্রহণকারীদের:

      • নাম: মাইকেল অ্যান্ড্রু, শহর: এডিনা, মার্কিন যুক্তরাষ্ট্র, ভূমিকা: লেন 1
      • নাম: জেন ওয়াডেল, শহর: ব্লিমফন্টেইন, দক্ষিণ আফ্রিকা, ভূমিকা: লেন 2
      • নাম: এভজেনি রাইলভ, শহর: নোভোট্রয়েটস্ক, রাশিয়া, ভূমিকা: গলি 3
      • নাম: ক্লিমেন্ট কোলেস্নিকভ, শহর: মস্কো, রাশিয়া, ভূমিকা: লেন 4

      // এবং তাই লেন 5 থেকে লেন 8 (উত্স: উইকিপিডিয়া

একজন সাঁতারু শুধুমাত্র একটি উত্তাপে একবার উপস্থিত হতে পারে এবং একটি লেন উত্তাপে একবারে দখল করা যায়।

আমি গিটহাবের কোডটি রেখেছি: https://github.com/cezar77/comp یتی ।

আবার সব ক্রেডিট দানি হেরেরে যায়। আমি আশা করি এই উত্তরটি পাঠকদের জন্য কিছু বাড়তি মূল্য সরবরাহ করবে।

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