Pregunta

Tenemos una aplicación de Django, que contiene una lista de artículos de prensa. Cada artículo tiene una relación M2M tanto con un "portavoz", así como una "firme" (empresa mencionada en el artículo).

Por el momento, la página Agregar artículo para la creación de nuevos artículos es bastante cerca de lo que queremos -. Es sólo la acción de administración de Django, y estamos usando filter_horizontal para el establecimiento de las dos relaciones M2M

El siguiente paso fue añadir un campo "Nota" como un campo intermediario en cada relación M2M.

Por lo tanto, un ejemplo de nuestra models.py

class Article(models.Model):
    title = models.CharField(max_length=100)
    publication_date = models.DateField()
    entry_date = models.DateField(auto_now_add=True)
    abstract = models.TextField() # Can we restrict this to 450 characters?
    category = models.ForeignKey(Category)
    subject = models.ForeignKey(Subject)
    weekly_summary = models.BooleanField(help_text = 'Should this article be included in the weekly summary?')
    source_publication = models.ForeignKey(Publication)
    page_number = models.CharField(max_length=30)
    article_softcopy = models.FileField(upload_to='article_scans', null=True, blank=True, help_text='Optionally upload a soft-copy (scan) of the article.')
    url = models.URLField(null=True, blank=True, help_text = 'Enter a URL for the article. Include the protocl (e.g. http)')
    firm = models.ManyToManyField(Firm, null=True, blank=True, through='FirmRating')
    spokesperson = models.ManyToManyField(Spokeperson, null=True, blank=True, through='SpokespersonRating')

    def __unicode__(self):
        return self.title

class Firm(models.Model):
    name = models.CharField(max_length=50, unique=True)
    homepage = models.URLField(verify_exists=False, help_text='Enter the homepage of the firm. Include the protocol (e.g. http)')

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ['name']

class Spokeperson(models.Model):
    title = models.CharField(max_length=100)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.first_name + ' ' + self.last_name

    class Meta:
        ordering = ['last_name', 'first_name']

class FirmRating(models.Model):
    firm = models.ForeignKey(Firm)
    article = models.ForeignKey(Article)
    rating = models.IntegerField()

class SpokespersonRating(models.Model):
    firm = models.ForeignKey(Spokesperson)
    article = models.ForeignKey(Article)
    rating = models.IntegerField()

El problema aquí es que una vez que cambiamos nuestra firma y el campo portavoz a "a través de" e intermediarios de uso, nuestra página Agregar artículo ya no tiene un control filter_horizontal añadir Empresas / relaciones vocero del artículo - que desaparezcan por completo. No se puede ver en absoluto. No tengo idea de por qué esto es.

Me estaba esperando para que haya alguna manera de seguir usando el fresco filter_horizontal widget para establecer la relación, y de alguna manera simplemente incrustar otro campo de abajo que para establecer la calificación. Sin embargo, no estoy seguro de cómo hacer esto sin dejar de aprovechar de la administración de Django.

vi una valoración crítica aquí sobre anulando una sola Widget en Django de administración:

http://www.fictitiousnonsense.com/archives/22

Sin embargo, no estoy seguro de si ese método sigue siendo válida, y no estoy seguro acerca de su aplicación a aquí, con una FK a un modelo intermediario (que es básicamente una línea entonces?).

Sin duda, hay una manera fácil de hacer todo esto?

Cheers, Victor

¿Fue útil?

Solución

El problema es que formfield_for_manytomany método del admin en django.contrib.admin.options no devuelve un campo de formulario para los campos ManyToMany con un modelo intermediario! http://code.djangoproject.com/browser /django/trunk/django/contrib/admin/options.py#L157

tendría que reemplazar este método en su ModelAdmin:

def formfield_for_manytomany(self, db_field, request=None, **kwargs):
    """
    Get a form Field for a ManyToManyField.
    """
    # If it uses an intermediary model that isn't auto created, don't show
    # a field in admin.
    if not db_field.rel.through._meta.auto_created:
        return None    # return something suitable for your needs here!
    db = kwargs.get('using')

    if db_field.name in self.raw_id_fields:
        kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel, using=db)
        kwargs['help_text'] = ''
    elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
        kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top