दानी हेरेरा का पहले से ही एक शानदार जवाब है , हालांकि मैं इसके बारे में विस्तार से बताना चाहता हूं।
जैसा कि दूसरे विकल्प में बताया गया है, ओपी द्वारा आवश्यक समाधान डिजाइन को बदलने और दो अद्वितीय बाधाओं जोड़ी को लागू करने के लिए है। बास्केटबॉल मैचों के साथ समानता समस्या को बहुत ही व्यावहारिक तरीके से दर्शाती है।
एक बास्केटबॉल मैच के बजाय, मैं फुटबॉल (या सॉकर) गेम के साथ उदाहरण का उपयोग करता हूं। एक फुटबॉल गेम (जिसे मैं इसे कहता हूं 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 जीएमटी
- प्रतिभागियों:
- नाम: लिवरपूल, शहर: लिवरपूल
- नाम: शस्त्रागार, शहर: लंदन
अब हमें प्रश्न से मुद्दे को हल करना होगा। Django स्वचालित रूप से कई-कई संबंधों के साथ मॉडल के बीच एक मध्यवर्ती तालिका बनाता है, लेकिन हम एक कस्टम मॉडल का उपयोग कर सकते हैं और आगे के फ़ील्ड जोड़ सकते हैं। मैं उस मॉडल को कॉल करता हूं Participant
:
वर्ग प्रतिभागी (मॉडल। मॉडल):
रोल्स = (
('एच', 'होम'),
('वी', 'आगंतुक'),
)
घटना = मॉडल। ForeignKey (घटना, on_delete = model.CASCADE)
प्रतियोगी = मॉडल। ForeignKey (प्रतियोगी, on_delete = model.CASCADE)
भूमिका = मॉडल.चार्फिल्ड (मैक्सिमम = 1, विकल्प = रोल)
कक्षा मेटा:
अनूठे_तो = (
('घटना', 'भूमिका'),
('घटना', 'प्रतियोगी'),
)
डीई __str __ (स्व):
वापसी '{} - {}'। स्वरूप (स्वयंवर, स्व .get_role_display ())
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 टीमों को नहीं जोड़ा जा सकता है।
यह एक अलग उपयोग के मामलों के लिए refactored जा सकता है। मान लीजिए कि हमारे कार्यक्रम तैराकी प्रतियोगिताओं हैं और घर और आगंतुक के बजाय, हमारे पास 1 से 8 तक गलियां हैं। हम सिर्फ 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())
इस संशोधन के साथ हमारे पास यह घटना हो सकती है:
एक तैराक केवल एक बार गर्मी में दिखाई दे सकता है, और एक गर्मी में केवल एक बार कब्जा किया जा सकता है।
मैंने GitHub: https://github.com/cezar77/competition पर कोड डाला ।
फिर, सभी क्रेडिट दानी हेरेरा को जाते हैं। मुझे आशा है कि यह उत्तर पाठकों को कुछ अतिरिक्त मूल्य प्रदान करता है।