When to use Content Types vs coding ContentPartRecords?

Topics: General
Nov 9, 2011 at 11:06 AM
Edited Nov 9, 2011 at 11:07 AM

It's dumb question time again. I think I'm missing somethig fundamental in how Orchard works in relation to contentTypes and Fields.

I was about to dive in and start creating a module to represent Company Profile information in my site. I thought I could model the Company,  CompanyType, CompanyAddress and other company info tables using Model classes and ContentTypeRecords and the appropriate Migration classes etc. ina  Module.

Then I thought why can't this be done using the Orchard front end using the ContentType, Fields and Content Parts already provided. I think my main stumbling block is deciding when to create custom data models and  when to use ContentTypes and fields to represent my data.

What are the best practices on deciding on when to create a module and how to start modelling your data? Apologies if this has been documented or discussed before and I have missed it.

Developer
Nov 9, 2011 at 12:45 PM

If you don't want to have many company infos on your site, just one (I'm not sure what's the case), then just make a new Page and list the info there.

The admin site gives a nice UI to drop together new content types from existing content parts and fields. Now if your content type (e.g. this company info, if you want to have a bunch of companies on your site) only needs to have parts or fields that are already present built-in or in some 3rd party module, this is the easiest way to go. If you plan to reuse this content type on other sites as well or you're the kind of person that likes to write code rather than click a content type together, than you could do the same (= build a content type out of existing parts and fields) in a module with Migrations. Actually such a module wouldn't need more than a Migrations implementation and a Module.txt.

Now if you want to have some fancy content part that is not present anywhere (like you need a custom brochure box for every company), than you need to implement a new content part, and then use this content part attached to a content type. This "attaching" can be done as described above.

Hope that helps!

Nov 9, 2011 at 1:36 PM

There are so many ways to model things in Orchard, it can certainly be difficult to figure out the best way sometimes! Here's my take (although it's pretty similar to Piedone's advice):

I've ended up modelling most things as content types. It just gives you the greatest amount of flexibility for choosing how your models behave and render. If there is a unit of data that I need on my model that can't be neatly described either by modelling another content type or by reusing an existing part/field, then at that point I'll build a new part.

Note: I wrote a module called Mechanics, which allows you to model any n-n relationships between content items, just by building new "connector" content types in admin. This is largely why I model everything I possibly can as content, because I then have an easy system for defining the relationships between them (and I get flexible rendering mechanisms and appropriate UI for free). Mechanics is available on Codeplex, but I should warn that most people have found it pretty hard to use. Personally I'm applying it to nearly every situation and it works great, but then I wrote it so I know how to get the most out of it. The current version on Orchard module gallery is out of date and incredibly buggy, so if it sounds useful make sure you grab the latest source. Finally, I'm about to undergo a major refactoring for performance, display and UI improvements; until that's finished I wouldn't hugely recommend looking too hard at the project unless you're fearless in the face of such things!

There are still some situations where I will model things as plain database tables and avoid the whole content database. This is generally where I have a performance-critical, very focussed task (and even then I sometimes find myself missing the extensibility of content!) An example would be the Logging module I've been talking about in another thread - it seems wholly inappropriate to store a log/audit record as a content item, and so I created a dedicated table.

Ultimately these are design/architectural decisions and unfortunately there is never really any one "best practise", just whatever seems most appropriate in a given situation.

Nov 9, 2011 at 2:51 PM
Edited Nov 9, 2011 at 3:04 PM
Piedone wrote:
Now if you want to have some fancy content part that is not present anywhere (like you need a custom brochure box for every company), than you need to implement a new content part, and then use this content part attached to a content type. This "attaching" can be done as described above.

Thanks, that definitely looks like the way I'm going. I'll have lots of Company items (records) and I need to maintain a resuable Company Profile for every company that can also contain reviews and other content parts. This is where the concepts of Orchard can become very confusing in the beginning. I don't mind writing the code but if there's an infrastructure already avalable then it's better to use it. It's taken me a good while to figure out that what I need to do is develop a new Content Part.

So, one last question. Do you have to write a module to create a Content Part? (as per creating a content part)

Nov 9, 2011 at 3:00 PM
Edited Nov 9, 2011 at 3:07 PM
randompete wrote:

There are so many ways to model things in Orchard, it can certainly be difficult to figure out the best way sometimes! Here's my take (although it's pretty similar to Piedone's advice):

I've ended up modelling most things as content types. It just gives you the greatest amount of flexibility for choosing how your models behave and render. If there is a unit of data that I need on my model that can't be neatly described either by modelling another content type or by reusing an existing part/field, then at that point I'll build a new part.

 

Thanks Randompete, I'm trying to leverage the Content Types as much as possible without having to reinvent the wheel. I did try your Mechanics module after you recommended it previously but as you say I think it had a few issues and wouldn't build.

When you add a Content Part to an existing Content Type, does this create any underlying relationships (1-n / n-n) between them automatically?

Developer
Nov 9, 2011 at 3:09 PM
brendan99 wrote:

Do you have to write a module to create a Content Part? (as per creating a content part)

Yes. A content part has its own ContentPart class, own ContentPartRecord if necessary, own drivers, handlers, a migration....

Nov 9, 2011 at 3:37 PM
brendan99 wrote:

Thanks Randompete, I'm trying to leverage the Content Types as much as possible without having to reinvent the wheel. I did try your Mechanics module after you recommended it previously but as you say I think it had a few issues and wouldn't build.

When you add a Content Part to an existing Content Type, does this create any underlying relationships (1-n / n-n) between them automatically?

If you just downloaded Mechanics from the gallery it wouldn't work; you need Origami as well (which does some fairly nifty things with shape composition). Certainly the current version on Codeplex (branches "default" or "1.2 compatible") is functional and operates stably - I have websites running on it. But, it'll be way better after my next set of updates, and currently it doesn't support versioning terribly well (...although it'll work with versioned items, you just don't get versioning on the relationships).

To answer your second question: basically, Content Parts have a 1:1 relationship with their Content Item. So each time you create a content item you'll get a 1:1 joined record for each part on that content type. Versioning makes things more complicated: you get a 1:n relationship between content item records and content item version records, and a 1:1 relationship between content item version records and versionable content part records. I hope that makes sense!

Nov 9, 2011 at 4:02 PM

Not sure about the versioning but I think I get the rest. So is it possible to use Lists of containable types to represent a 1- n relationship between types or is that pushing it?

Nov 9, 2011 at 4:13 PM

Container/Containable lists already represent 1-n relationships (you don't need my module for that, it's part of Orchard core). But they're quite limiting and if you want more than 1 type of relationship from any given content item, and especially if you want n-n, then that's where you need to drop Containable and find another way - either by manually implementing relationships, or by using Mechanics, or using Sebastien's Taxonomies module which also manages certain kinds of relationships.

Nov 9, 2011 at 4:33 PM

Excellent, I think I see the light now. Thanks for clearing this up.