Using Cartridge's cart without its products/categories

201 views
Skip to first unread message

Alexander Hill

unread,
May 9, 2012, 3:38:53 AM5/9/12
to mezzani...@googlegroups.com
Hi everyone!

I'm trying to settle on a shopping cart for an upcoming project.

The user-facing shop will need to be handmade as we want to do filtering/searching based on our products' attributes (think about a car sales website where you can filter by year, body type, etc). So really I just need the actual cart part - adding products to a cart, wishlists, coupon codes, payment processing, etc.

How easy would it be to use those parts of Cartridge without using the category and product models? I'm thinking I would have to define my own view for adding to the cart, in which I call pass something which quacks like a ProductVariation to cart.add_item(). Since the items stored in the cart/order models are denormalised and don't refer to Products or ProductVariations, I feel like this might work. Obviously I'm not very familiar with the codebase though.

I want to use Cartridge because I'm really impressed by the commitment to the project from Stephen and others in this group, and because I'd like to use Mezzanine for the rest of the site. The other options would be Plata or Django-shop, both of which do seem a bit more targeted at this kind of use.

Any thoughts or suggestions would be appreciated.

Cheers,
Alex

Stephen McDonald

unread,
May 9, 2012, 4:51:19 PM5/9/12
to mezzani...@googlegroups.com
At the moment you're tied to the Product model in Cartridge, so I'd suggest trying to layer things onto it rather than replacing it.

Gary Reynolds and I have been recently discussing how this might be more configurable. I'm not sure if there's any code there yet (Gary if you read this and there is, please correct me), but we talked about having a setting in the shop that would point to the path for the product model to use, and the product model would be loaded from it in each module that references the product model. Something like:

SHOP_PRODUCT_MODEL = "show.models.Product"

Then in each module, instead of importing shop.models.Product:

Product = import_dotted_path(settings.SHOP_PRODUCT_MODEL)

This would be a fairly lightweight change so if Gary hasn't worked on that yet then feel free to kick it off. Of course as you alluded to, the custom model you use would need to do a lot of quacking for everything to work - but making that less of a thing would be the next step of evolution for it.
--
Stephen McDonald
http://jupo.org

Gary Reynolds

unread,
May 9, 2012, 5:40:59 PM5/9/12
to mezzani...@googlegroups.com
I haven't made any start on this, so feel free to dive in.

I would recommend that we have a very basic class which we provide, ProductBase, which has Meta.abstract = True and we can provide a concrete implementation as Product that gives a demonstration of how to implement a custom product class. Any quacking could be implemented here, and subclasses would be for adding custom fields or behaviours. Of course, a developer could always choose to not subclass ProductBase for total control.

Further, I would avoid import_dotted_path for this one. I think using django.db.models.loading.get_model(settings.SHOP_PRODUCT_MODEL) because we can then have ForeignKey relations point to the same setting (as a string value). It would change it from a full dotted path to an app.label (default would be "shop.Product") but I think since we have ProductVariation et al which link back to Product, this will be a necessity. Certainly this will require some testing.

Gary

Josh Cartmell

unread,
May 10, 2012, 2:14:16 AM5/10/12
to mezzani...@googlegroups.com
I like where you are going with that Gary and I was wondering would there be any way to abstract products further the way that pages are (so we wouldn't set abstract=True)?  A product would be anything that subclassed ProductBase and by not setting abstract to true it would give some of the power that we currently have with Mezzanine Page subclasses.  You could have multiple kinds of products and not be restricted to one via a setting.  I imagine a shop could then sell downloadable products and physical products.  The base product model could potentially have some overridable method that is run when an order is complete allowing you to implement extra logic that a particular product type required.

I'm not sure how feasible this is but I think abstracting the Products a bit more like Pages could provide some interesting opportunities and great power and flexibility while avoiding adding another setting.  Thoughts?

Gary Reynolds

unread,
May 10, 2012, 5:18:32 AM5/10/12
to mezzani...@googlegroups.com
Anything that subclasses whatever model is defined by SHOP_PRODUCT_MODEL would still work.

Here is how I would see it:
  1. we have cartridge.shop.models.ProductBase which is indeed abstract, but provides methods for it to quack like we expect
  2. we have cartridge.shop.models.Product will inherit from ProductBase and shall implement anything more than what was refactored into the abstract base
  3. the default value for SHOP_PRODUCT_MODEL will be "shop.Product"
This should all be relatively easy to change and maintain backwards compatibility.

Now, a developer who wants to provide downloadable content could add myapp.models.DownloadProduct which inherits from Product. Alternatively, they might have a custom SHOP_PRODUCT_MODEL and DownloadProduct could instead inherit from it, and the ProductVariation table would still point to the SHOP_PRODUCT_MODEL.

This is vanilla model inheritance, we wouldn't need to write anything additional at all?

Stephen McDonald

unread,
May 11, 2012, 7:36:23 AM5/11/12
to mezzani...@googlegroups.com
This sounds spot on if anyone wants to pick it up.

Josh Cartmell

unread,
May 11, 2012, 12:37:52 PM5/11/12
to mezzani...@googlegroups.com
Forgive me if I'm being dense but why wouldn't we just create a non abstract base product that quacks like a product and then allow users to create their own product types through multi table inheritance (like the Page model)?

Then we would always import ProductBase and custom product stuff would be accessible via productbase.customproduct (the same way you can get page.form or page.gallery).  The reason that I am pressing this point is that I see value in consistency which could make it easier for a developer to jump from Mezzanine to Cartridge.  With that in mind what are the advantages of the setting vs. Page like multi table inheritance?

Gary, I know I have ended up on the opposite side of a number of ideas/issues from you but I have truly appreciated your contributions and explanations so thank you.

Gary Reynolds

unread,
May 11, 2012, 5:45:01 PM5/11/12
to mezzani...@googlegroups.com
A fair question.

My intent is to provide an optimal solution for normal use. "Enforcing" multi-table inheritance does not satisfy that for me.

I think most shops won't have a mix of product types but customisations are very likely, so if they do want to customise Product and have extra fields or methods they should be able to get that without needing a join on every query.

Currently they can fudge the extra fields with EXTRA_MODEL_FIELDS, but that isn't particularly kosher in my book - this is cleaner & explicit.

I don't mind the healthy discussion/opposition at all, it helps us all clarify a position.

Cheers
Gary

Gary Reynolds

unread,
May 11, 2012, 7:50:30 PM5/11/12
to mezzani...@googlegroups.com
I should also have mentioned that there is nothing stopping a developer subclassing the current Product right now, we're just formalising a way to let developers _replace_ the default model if their needs demand it.

It might be interesting if once a refactor was complete, someone could contribute back to the project a DownloadProduct or similar alternative implementation that can be used as a blueprint for others to follow.

Gary

Stephen McDonald

unread,
May 11, 2012, 8:49:25 PM5/11/12
to mezzani...@googlegroups.com
One thing going for the concrete inheritance is that I think some relationships don't work with abstract classes - I haven't dealt with this for a while so my understanding might be outdated, but I have a standalone version of mezzanine.forms called django-forms-builder which has abstract versions of everything and hit that wall when I was doing that: https://github.com/stephenmcd/django-forms-builder/blob/master/forms_builder/forms/models.py#L245

The thing going for abstract models is some potential performance benefit without DB joins - this could be bigger than we think if the products are being iterated through with concrete inheritance and the subclass is being accessed inside the loop - we'd need to be sure this doesn't happen, but it might not be a problem with concrete inheritance if we ensure all accessing of products always deals with the subclass.

Jim Myers

unread,
May 19, 2012, 1:02:10 PM5/19/12
to mezzani...@googlegroups.com
I just found this thread and am hoping this work is progressing.

I've been looking at how to fit my project with Cartridge and this looks like the best candidate so far.
I too have a lot of "variations" that I don't want to have to create by going through the admin.

I think with this approach I could dynamically create what I need to both show to a customer and to put in a cart.

So what's the status of this?

Stephen McDonald

unread,
May 19, 2012, 5:06:45 PM5/19/12
to mezzani...@googlegroups.com
Nothing's happened yet on my end.

Can you describe your use case more? It doesn't sound related to this.

Jim Myers

unread,
May 20, 2012, 2:31:31 PM5/20/12
to mezzani...@googlegroups.com
I guess it's not quite the same but similar. I want to sell recordings of events, but there are many (hundreds, eventually thousands)  events and recordings. I do not want to create a Variation for each event/recording. I just want one (or a small number anyway) of static Products with which I can dynamically associate the particulars, i.e. the actual event/recording to be purchased/downloaded.

Alexander Hill

unread,
May 23, 2012, 10:10:59 PM5/23/12
to mezzani...@googlegroups.com
Hi all,

I've been thinking about the ideas discussed in this thread, and I'd like to throw in my two cents.

At the moment, products are conceptually split between Product, ProductVariation and ProductOption. Being able to replace Product is great and that work should continue, but it only gets us part of the way to full customisation. We're still tied to Cartridge's options+variations paradigm, which is perfect for a lot of products but not everything.

I propose creating a well-defined interface cleanly separating the shop into two parts: the shopfront, and the shopping cart. This should be done with a couple of goals in mind.

Firstly, we should be able to add anything to the cart, by simply specifying an sku, description, price, quantity, image, etc - the things that are stored in CartItem now. Secondly, all of the code which provides the cart with info about its items - stock levels, working out discounts, upsell products, etc - should all be in one, easily-overrideable place. That could be a refactored Product model (bad idea), an entirely new interface class between carts and products, or on the cart itself, by providing an abstract CartBase and default implementation which can be replaced.

In my experience the requirements for the shopfront are much more variable than those for the cart. This arrangement would allow developers to swap out the online shopfront entirely if it doesn't fit the product they're selling, while still being able to rely on a well-tested and robust cart. It also lends neatly to integration with existing stock management systems.

Eventually, I'd like to see the two parts of the shop in two separate apps, with the shopfront app depending on the cart.

I'm keen to hear what everybody thinks about this. A shop with this functionality would be incredibly useful to me and I would be happy to put in the hours required to make it happen if people like the idea.

Alex

Gary Reynolds

unread,
May 23, 2012, 10:30:18 PM5/23/12
to mezzani...@googlegroups.com
I propose creating a well-defined interface cleanly separating the shop into two parts: the shopfront, and the shopping cart. This should be done with a couple of goals in mind.

I agree, and I've had a similar thing in mind for a while, I just hadn't had a way to express it.
 
Firstly, we should be able to add anything to the cart, by simply specifying an sku, description, price, quantity, image, etc - the things that are stored in CartItem now. Secondly, all of the code which provides the cart with info about its items - stock levels, working out discounts, upsell products, etc - should all be in one, easily-overrideable place. That could be a refactored Product model (bad idea), an entirely new interface class between carts and products, or on the cart itself, by providing an abstract CartBase and default implementation which can be replaced.

Idea needs fleshing out, but in principle ... yep!
 
In my experience the requirements for the shopfront are much more variable than those for the cart. This arrangement would allow developers to swap out the online shopfront entirely if it doesn't fit the product they're selling, while still being able to rely on a well-tested and robust cart. It also lends neatly to integration with existing stock management systems.

For sure. Template tags in the cart application could provide the hooks to allow any shop item to be added to the cart. Essentially sku & quantity, there should be a function to resolve the product from the sku.
 
Eventually, I'd like to see the two parts of the shop in two separate apps, with the shopfront app depending on the cart.

If possible, I'd like to even keep that separate. I can see a case where a collection of products with prices, sizes, etc might form part of a website, but online sales are not accepted; it would save a developer constructing a product catalogue application specifically.

I'm keen to hear what everybody thinks about this. A shop with this functionality would be incredibly useful to me and I would be happy to put in the hours required to make it happen if people like the idea.

I think it's an interesting direction. However I suspect that it is quite radical and won't be easily accomplished by modifying cartridge as it stands, I think there is too much friction to overcome. This does not prevent a spin-off being born.

Gary

ping yang

unread,
Jan 24, 2018, 11:17:45 AM1/24/18
to Mezzanine Users
Hi Alex,
I get into this discussion which you posted long time ago, Did you get any success on using cartridge/mezznine for your shopping cart project?
I want to customize the default setting for a restaurant online order I am eager to know if there are some experiences you can share.
Looking forward to hearing from you.
Thanks,
Peter
Reply all
Reply to author
Forward
0 new messages