django admin many-to-many intermediary models using through= and filter_horizontal

后端 未结 3 1869
悲哀的现实
悲哀的现实 2020-12-05 03:08

This is how my models look:

class QuestionTagM2M(models.Model):
    tag = models.ForeignKey(\'Tag\')
    question = models.ForeignKey(\'Question\')
    date_         


        
3条回答
  •  时光取名叫无心
    2020-12-05 03:45

    There are ways to do this

    • As provided by @obsoleter in the comment below : set QuestionTagM2M._meta.auto_created = True and deal w/ syncdb matters.
    • Dynamically add date_added field to the M2M model of Question model in models.py

      class Question(models.Model):
          # use auto-created M2M model
          tags = models.ManyToMany(Tag, related_name='questions')
      
      
      # add date_added field to the M2M model
      models.DateTimeField(auto_now_add=True).contribute_to_class(
               Question.tags.through, 'date_added')
      

      Then you could use it in admin as normal ManyToManyField.
      In Python shell, use Question.tags.through to refer the M2M model.

      Note, If you don't use South, then syncdb is enough; If you do, South does not like this way and will not freeze date_added field, you need to manually write migration to add/remove the corresponding column.

    • Customize ModelAdmin:

      1. Don't define fields inside customized ModelAdmin, only define filter_horizontal. This will bypass the field validation mentioned in Irfan's answer.
      2. Customize formfield_for_dbfield() or formfield_for_manytomany() to make Django admin to use widgets.FilteredSelectMultiple for the tags field.
      3. Customize save_related() method inside your ModelAdmin class, like

    def save_related(self, request, form, *args, **kwargs):
        tags = form.cleaned_data.pop('tags', ())
        question = form.instance
        for tag in tags:
            QuestionTagM2M.objects.create(tag=tag, question=question)
        super(QuestionAdmin, self).save_related(request, form, *args, **kwargs)
    
    • Also, you could patch __set__() of the ReverseManyRelatedObjectsDescriptor field descriptor of ManyToManyField for date_added to save M2M instance w/o raise exception.

提交回复
热议问题