2009-05-19 18 views
29

Desidero collegare un singolo ForeignKey a due modelli diversi.Come utilizzare la foreignkey dinamica in Django?

Ad esempio:

Ho due modelli denominati Casts e Articles, e un terzo modello, Faves, per favoriting uno degli altri modelli. Come posso rendere dinamico il ForeignKey?

class Articles(models.Model): 
    title = models.CharField(max_length=100) 
    body = models.TextField() 

class Casts(models.Model): 
    title = models.CharField(max_length=100) 
    body = models.TextField() 

class Faves(models.Model): 
    post = models.ForeignKey(**---CASTS-OR-ARTICLES---**) 
    user = models.ForeignKey(User,unique=True) 

È possibile?

risposta

37

Ecco come lo faccio:

from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import fields 


class Photo(models.Model): 
    picture = models.ImageField(null=True, upload_to='./images/') 
    caption = models.CharField(_("Optional caption"),max_length=100,null=True, blank=True) 

    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = fields.GenericForeignKey('content_type', 'object_id') 

class Article(models.Model): 
    .... 
    images  = fields.GenericRelation(Photo) 

Si potrebbe aggiungere qualcosa come

content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = fields.GenericForeignKey('content_type', 'object_id') 

ai favoriti e

fields.GenericRelation(Faves) 

dell'articolo e Fusioni

contenttypes docs

15

Ecco un approccio. (Si noti che i modelli sono singolari, Django pluralizes automaticamente per voi.)

class Article(models.Model): 
    title = models.CharField(max_length=100) 
    body = models.TextField() 

class Cast(models.Model): 
    title = models.CharField(max_length=100) 
    body = models.TextField() 

FAVE_CHOICES = ( 
    ('A','Article'), 
    ('C','Cast'), 
) 
class Fave(models.Model): 
    type_of_fave = models.CharField(max_length=1, choices=FAVE_CHOICES) 
    cast = models.ForeignKey(Casts,null=True) 
    article= models.ForeigKey(Articles,null=True) 
    user = models.ForeignKey(User,unique=True) 

Questo presenta raramente problemi profondi. Potrebbe richiedere alcuni metodi di classe intelligenti, a seconda dei casi d'uso.

+10

+1 Penso che i tipi di contenuti generici, come nella risposta accettata, siano migliori per i modelli "collegabili" in cui non si conosce nulla delle relazioni. La tua risposta è migliore per le situazioni in cui hai il controllo e la conoscenza completa di tutti i modelli. Migliore significa più facile scrivere query e meno risultati nel database. –

+2

Hai dimenticato "null = True" nel cast e il campo FK dell'articolo args perché ogni istanza di Fave non imposterà il solo campo FK su Nessuno che corrisponde all'impostazione nel campo type_of_fave – Geradeausanwalt

Problemi correlati