اذهب إلى المحتوى

السؤال

نشر

لاحظ أنه عند إنشاء علاقة بين نموذجين أننا نستعمل OneToOneField أو ForeignKey، ولكن ما هو الإختلاف بينهما؟  أليس كلاهما يقوم بعمل علاقة بين جدولين؟

وفي حالة وجود إختلاف، هل يمكن لأحدهما أن يقوم بعمل الآخر بطريقة مختلفة؟ أي هل يمكن أن يستبدل أحدهما الآخر؟

Recommended Posts

  • 1
نشر

OneToOneField يمثل علاقة (one-to-one) ويمثل مفهوم ال composition (التركيب) في الكائنات object، بينما ForeignKey  يمثل (one-to-many)  ويمثل مفهوم ال agregation أو التجميع للكائنات.
OneToOneField هي علاقة واحد لواحد كما ذكرنا وهي مشابهة لحالة ForeignKey  مع تحديد قيمة unique على True، ولكن في حالة reverse سيعيد كائناً واحداً مباشرةً. أما ForeignKey  فستعيد QuerySet.

(one-to-one field )(one-to-one)== (ForeignKey with unique=True)(one-to-many)
ForeignKey ="reverse" relation returns a QuerySet.  # وستعيد QuerySet
one-to-one field = "reverse"  يعيد كائن واحد مباشرةً

سأعطيك الآن مثال عملي لتفهمهم بشكل أفضل. افترض للحظة أنك تريد إنشاء مدونة في django حيث يمكن للصحفيين كتابة المقالات الإخبارية ونشرها. يريد مالك الصحيفة الإلكترونية أن يسمح لكل من مراسليه بنشر العديد من المقالات التي يريدونها ، لكنه لا يريد أن يعمل مراسلين مختلفين على نفس المقالة. هذا يعني أنه عندما يذهب القراء ويقرأون مقالًا ، فإنهم لن يروا سوى مؤلف واحد في المقالة.
على سبيل المثال: مقال بقلم محمد، مقالة بقلم علي، مقالة بقلم إياد. لا يمكنك الحصول على مقال بواسطة محمد & علي لأن المدير لا يريد مؤلفين أو أكثر للعمل على نفس المقالة.
كيف يمكننا حل هذه "المشكلة" بمساعدة django؟ مفتاح حل هذه المشكلة هو django ForeignKey.
فيما يلي الكود الكامل الذي يمكن استخدامه لتنفيذ فكرة رئيسنا.

from django.db import models
# أنشئ النموذج أولاً هنا
class Reporter(models.Model):
    first_name = models.CharField(max_length=30)
    def __unicode__(self):
        return self.first_name
class Article(models.Model):
    title = models.CharField(max_length=100)
    reporter = models.ForeignKey(Reporter)
    def __unicode__(self):
        return self.title

الآن:

# يُستخدم لتحديد العلاقات بين شخص وآخر  django ForeignKey  يوضح لنا هذا المثال العملي التالي أن
#لإنشاء علاقات واحد لواحد OneToOneField بينما
# إنشاء Reporter object R1
from thepub.models import Reporter, Article
R1 = Reporter(first_name='Ali')
R1.save()
# إنشاء Article object A1.
A1 = Article.objects.create(title='TDD In Django', reporter=R1)
A1.save()
# الحصول على اسم الناشر
A1.reporter.first_name
'Ali'
# إنشاء آخر
R2 = Reporter.objects.create(first_name='Mohamed')
R2.save()
# الآن حاول إضافته للمقالة السابقة
A1.reporter.add(R2)
# AttributeError  سنحصل على خطأ
# كما ترى ، لا يمكن ربط كائن مقال بأكثر من كائن ريبورتير واحد.
#r1 الآن لنجرب إرفاق أكثر من مقال ل 
A2 = Article.objects.create(title='Python News', reporter=R1)
R1.article_set.all()
# [<Article: Python News>, <Article: TDD In Django>]

 

  • 0
نشر

هناك بعض الاختلافات بين OneToOneField و ForeignKey . كما ورد في الدليل النهائي لـ Django
OneToOneField  علاقة one-to-one . من الناحية المفاهيمية ، هذا مشابه لـ ForeignKey مع unique=True ، ولكن الجانب العكسي من العلاقة سيعيد كائن واحد بشكل مباشر. بالتباين مع علاقة OneToOneField العكسية تقوم علاقة ForeignKey العكسية بإرجاع QuerySet. على سبيل المثال ، إذا كان لدينا النموذجان التاليان

  • نموذج car يستخدم OneToOneField
  • نموذج Car2 يستخدم ForeignKey مع unique=True

مثال OneToOneField 

 from testapp.models import Car, Engine
 c = Car.objects.get(name='Audi')
 e = Engine.objects.get(name='Diesel')
 e.car
<Car: Audi>

مثال ForeignKey مع unique=True

 from testapp.models import Car2, Engine2
 c2 = Car2.objects.get(name='Mazda')
 e2 = Engine2.objects.get(name='Wankel')
 e2.car2_set.all()
[<Car2: Mazda>]

كود النموذج

from django.db import models

class Engine(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)

    def __unicode__(self):
        return self.name

class Engine2(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)

    def __unicode__(self):
        return self.name

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...