0

I am using a Wagtail streamfield to allow users to upload and link to documents in the editor interface. Originally, I tried to use a foreign key as referenced in the documentation and as all other examples I have seen. I kept getting an error when running migrations that wagtail document has not property "set name". So I decided to not use a foreign key because these documents do not necessarily need to be related on a one-to-many relationship for our purposes. So in my model, I do not use a foreign key for all the fields using DocumentChooserBlocks and everything seems to work fine. Am I misunderstanding "foreign key" and making a mistake(or practicing bad DB design). Here is my working model for this:

class AgendaPage(Page):
author= models.CharField(max_length=255)
date = models.DateField('Post date')
mtg_date = models.DateField(default=datetime.date.today)
mtg_time = models.CharField(max_length=255, default ='10:00 AM')
full_video_url-models.CharField(required =False)
###full_audio = DocumentChooserBlock(required=False)
###mtg_transcript = DocumentChooserBlock(required=False)
])
agenda = StreamField([
    ('agenda_item', blocks.StreamBlock([
        ('item_title', blocks.TextBlock()),
        ('item_text', blocks.TextBlock()),
        ('mtg_doc', blocks.StructBlock([
            ('mtg_doc_upload', DocumentChooserBlock(required=True)),
            ('submitted_late', blocks.BooleanBlock(required=False, help_text='Submitted Late')),
            ('heldover', blocks.BooleanBlock(required=False, help_text='Held Over')),
            ('heldover_from', blocks.DateBlock(required=False, help_text="Held Over From")),
        ])),
        ('item_audio', DocumentChooserBlock(required=False)),
    ]))
])




content_panels = Page.content_panels + [
    FieldPanel('author'),
    FieldPanel('date'),
    FieldPanel('mtg_date'),
    FieldPanel('mtg_time'),
    StreamFieldPanel('agenda'),

]

Also, in the two commented-out lines in the model, I am trying to have a DocumentChooserBlock that is not inside a streamfield(without foreign key) I know this syntax is likely wrong, as all examples I see, define a forein key in the model definition, and then reference a DocumentChooser Panel in the panels definition. Is it is possible(or advisable) to do it without foreign key?

JohnnyP
  • 426
  • 1
  • 7
  • 12

1 Answers1

1

DocumentChooserBlock is never used with a foreign key. There are two distinct methods of attaching documents to pages, and you choose one or the other:

  • A ForeignKey to Document, with a DocumentChooserPanel in content_panels. This would be used when you have a one-to-one or many-to-one relation from pages to documents; for example, a ProductPage where a product has a PDF data sheet. This creates a formal link between the two objects at the database level.

  • A StreamField with a DocumentChooserBlock in it. This is used for more flexible arrangements, where the document link can appear at any position down a page. There's no formal association at the database level - from the database's point of view, a StreamField is just free text. This means there's no need for a ForeignKey.

gasman
  • 23,691
  • 1
  • 38
  • 56
  • How would I create a DocumentChooserPanel that is not within a streamfield, that does not have a foreign key? – JohnnyP Oct 17 '16 at 13:29
  • 1
    You wouldn't. The foreign key is the thing that allows the database to know that page X is associated with document Y. If you really, really want to avoid having a foreign key, you can use a plain Django FileField (https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.FileField) along with a FieldPanel, but that's a lot more primitive (you'll just get a plain 'upload' field, not the popup chooser interface). – gasman Oct 17 '16 at 20:11
  • I am going to go out on a limb ask this question: The why is it OK to not have a foreign key in a document upload in a streamfield? All these answers have educated me and gotten me closer to solution, but I am still obviously misunderstanding something. – JohnnyP Oct 17 '16 at 23:10
  • 1
    The StreamField itself handles that job. You can think of it this way: a ForeignKey reserves a spot in the database for a single piece of information (namely, a pointer to the linked document) while the DocumentChooserPanel tells the Wagtail admin to display it as a document chooser (rather than, say, a dropdown list). A StreamField reserves a spot in the database for a whole pile of information (the stream content, including any document references you put in there) while the StreamFieldPanel tells the Wagtail admin to display it with the standard "collapsible panels" StreamField behaviour. – gasman Oct 19 '16 at 11:05
  • Ahh, so an uploaded document, by nature, has a foreign key relationship (pointer) to a separate place in the DB. While a text field, for example, resides in the DB table for the page in which it is is input and does not need to reside somewhere else (unless specified by a foreign key)? – JohnnyP Oct 20 '16 at 21:20
  • Yep, that's exactly it. – gasman Oct 21 '16 at 09:39