I am using Djnago-oscar for Solar energy equipment based eCommerce site. I need to add an option to "Basket" model with "Battery Name", "Notes" and
"Manufacturer". There is a reason I don't want to add it in subclass AbstractProduct. Rather I want to built it with subclass Basket model.
Now I need help to understand my workflow to make this work with AddToBasket form. In Django-oscar/basket there are formsets.py using formset factory and a form.
I am a bit confused and decided to get help from community.
Following is the code:
models.py
MANUFACTURERS = (
('UPS SYSTEMS', 'UPS SYSTEMS'),
('VOLTA', 'VOLTA'),
('TOSHIBA ', 'TOSHIBA '),
)
BATTERIES = (
('LITHIUM', 'LITHIUM'),
('NICAD', 'NICAD'),
('NIFE ', 'NIFE '),
)
class AddBattery(AbstractBasket):
battery_name = models.CharField(max_length=1, choices=BATTERIES)
manufacturers = models.CharField(max_length=1, choices=MANUFACTURERS)
price = models.DecimalField(decimal_places=2, max_digits=6)
notes = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.battery_name
class Basket(AbstractBasket):
add_bat=models.ForeignKey(_(u'Add a Batter'), to=AddBattery, null=True, blank=True)
forms.py
from django import forms
from django.conf import settings
from django.db.models import Sum
from django.utils.translation import ugettext_lazy as _
from oscar.forms import widgets
from oscar.apps.basket.forms import BasketLineForm as CoreBasketLineForm,\
SavedLineForm as CoreSavedLineForm, BasketVoucherForm as CoreBasketVoucherForm,\
AddToBasketForm as CoreAddToBasketForm
from .models import AddBattery
from oscar.core.loading import get_model, get_classes
Line = get_model('basket', 'line')
Basket = get_model('basket', 'basket')
Product = get_model('catalogue', 'product')
class BasketLineForm(CoreBasketLineForm):
class AddBatteryForm(CoreBasketLineForm.Meta):
model = AddBattery
fields = ['battery_name', 'manufacturers', 'comment']
views.py
I need help to figure this part because it has so much nested elements and I couldn't get it right.
Help is much appreciated.
Templates:
I can work this out because I need admin to have ability to add it but end user only will have an option to select from with price.
Upon selection by client I need to have consolidated price with products and plus the battery. Any advise for this part would be great as well
about how to get consolidated price from both in cart for checkout.
Don't add your fields in Basket model. You need to subclass Line model instead.
Subclass forms.py and formsets.py. You only need to change BasketLineForm, SavedLineForm and AddBasketForm. After you subclass these in your own forms. Leave rest of the Forms.
Subclass BaseBasketLineFormSet and BaseSavedLineFormSet in your own formsets edit as per your need.
Subclass BasketView and AddBasketView by supplying the forms, formsets and args/kwargs you added.
Copy template directory from app to your own folder and add form at basket_total.html as you mentioned above as the last part.
But having said that...its against the workflow as explained by others. There is no limitation at all for you in any case as far as programming is concerned. But you should always consider the most reasonable path to solve your problems.
This is a very broad question with several different components. I can offer the following suggestions for you to look into:
Doing this in the basket model is almost certainly not going to serve you well, because you will not be able to pass this custom information to the order object when it is created. More importantly, what you're trying to do doesn't seem to be a basket issue, just a product/variant issue (see below).
There are two possibilities I can see from what you have described:
a. A battery is a separate product that the user buys along with the main product. It has its own pricing and availability.
b. A battery isn't a separate product, it's just one of a fixed set of choices that a customer has when buying the main product.
If (a), then you just need to have separate products, and some logic that allows a user to select the accessory product (battery) at the same time as the main one, and that adds both to the basket simultaneously.
If (b), then these are essentially variants where one product has multiple variations with different pricing. In this case you should use Oscar's built-in support for variants.
In any case, modifying the basket model will cause you a lot of problems IMO.
Related
I'm building a website listing poker tournaments. I would like to allow user mark some tournaments as his favourite and avoid forms or extra page with GET parameter - I would like to to update it without refreshing website. From what I understand, it's done by ajax and jquery. But there are many ajax libraries and I would like you to tell me, which one should I use and how to do this simple functionality best.
This is my tournament table:
I would like to have another column before event time, that would contain image for heart. It would be black (not favourite) and if user clicks on it, it would turn red (favourite).
I think m2m relationship should be used here. This is my tournament model.
class Tournament(models.Model):
favourite = models.ManyToManyField(User)
date = models.DateTimeField('Event time')
currency = models.CharField(max_length=5, choices=CURRENCIES, default='USD')
name = models.CharField("Tournament name", max_length=200)
prize = models.DecimalField(max_digits=20, decimal_places=2)
entry = models.DecimalField(max_digits=20, decimal_places=2)
fee = models.DecimalField(max_digits=20, decimal_places=2)
password = models.CharField("password", max_length=200)
type = models.ForeignKey('room.Type')
room = models.ForeignKey('room.Room')
requirements_difficulty = models.IntegerField('Tournament Difficulty',
validators=[MinValueValidator(1), MaxValueValidator(30)])
requirements_text = models.CharField("Requirements Description", max_length=1000)
recurrence = models.CharField(max_length=5,
choices=RECURRENCE_CHOICES,
default='NONE')
So how do I add m2m relationship between user and tournament? Do I use ajax code or dajax? How do I create this m2m without refreshing page?
So how do I add m2m relationship between user and tournament?
Assuming that you use the default django user model:
Class Tournament(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_tournament')
...
Do I use ajax code or dajax?
As #doniyor said, you should define your real problem and split your question. SO is not "do it for me", anyway, what I can do for you, is give you some good links ;)
W3 schools definition for ajax:
http://www.w3schools.com/ajax/ajax_intro.asp
Good ajax plugin for djando that seems you already know:
http://www.dajaxproject.com/
By the way, you should use dajax, is easy and faster to create ajax pages integrated with django (you just have to follow the tutorials, is pretty simple).
How do I create this m2m without refreshing page?
Using dajax
Hello and good day to all the members of this great community. I'm still new in PHP and especially in Magento.
I'm not posting, waiting for answers, and leaving without replying back. This is a learning process. I hope to get a great support from all of you.
I have a product. I did create custom option for the product, that is an attribute named "a_size". The attribute has value of S, M and L. Each of the value has quantity.
In the single product view, I would like to call all the available size. That is the size (S, M, or L) that has quantity more than 0. I just want to show the available size, not how much the size left.
Can anybody guide me? I'm using Magento 1.7.x and as far for this 2 weeks, I did try pretty many of suggested answers from the community thru the search function.
The replies will be much appreciated. Thank you.
There are a few things to try.
Firstly check that when you set up your new attribute in the Magento Admin (Catalog->Attributes->Manage Attribute) that in the Frontend Properties box you have set Visible on Product View Page on Front-end to yes.
To get size values I use this code:
$cabac_sizeAttribute = $_product->getAttributeText("a_size");
but I have other code for getting attribute values that goes like this:
$_product_helper = Mage::helper('catalog/output');
$temp = $_product_helper->productAttribute($_product, $_product->getASize(), 'a_size');
I think it is related to the type of attribute: text, dropdown, multiselect etc so try both and see how you get on. But really the function productAttribute() is just applying formatting. You can read the function in the file app/core/Mage/Catalog/Helper/Output.php
Also, I wonder, if you have set up a configurable product and you are on the product view page then you will be viewing the configurable product. That product won't have an a_size value: you are trying to access the a_size attribute of the simple products that make up the configurable product, yes? Everything I wrote above is (I think) correct but to get the attribute of the simple products that are part of a configured product you should study the code in the function getJsonConfig() of the file app/core/Mage/Catalog/Block/Product/View/Type/Configurable.php
And in particular to these lines:
//file: file app/core/Mage/Catalog/Block/Product/View/Type/Configurable.php
//class: Mage_Catalog_Block_Product_View_Type_Configurable
//function: getJsonConfig()
foreach ($this->getAllowProducts() as $product) {
$productId = $product->getId();
foreach ($this->getAllowAttributes() as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
$attributeValue = $product->getData($productAttribute->getAttributeCode());
Being careful about variable naming: $product is local here, I suggest changing it, and about $this - but if you are in a .phtml of the product view for configurables then I think your $this is already Mage_Catalog_Block_Product_View_Type_Configurable
Welcome to Magento coding. You are doing well; it is a long but rewarding path. (hints: local.xml is your vital friend and so is Alan Storm if you haven't come across his content yet.)
[Additionally, (welcome to Magento) I think you are trying to say eg S and L are out of stock and M is in stock but actually the function getAllowProducts() will disallow a product with zero stock and exclude it from the returned object. You will need to use
$allProducts = $this->getProduct()->getTypeInstance(true)
->getUsedProducts(null, $this->getProduct());
(taken from function getAllowProducts() in file app/core/Mage/Catalog/Block/Product/View/Type/Configurable.php)
and then, if needed, check that each product is allowed to be shown eg status=ENABLED, and then check its stock level...
]
Malachy.
If you want to get the values of your drop down attribute use the following code
$_product->getASize();
and initially load the product object
Currently I'm developing a debate module (much like a scrum/kanban board) for a GPL application (e-cidadania) and I don't have any experience with complex backends. I have developed a basic frontend for it, but now I don't know what approach I should use for the ajax and django backends to save and manipulate the table and notes.
The table can be N rows and N columns, every row and column has a name and position inside the table. Every note has also a position, text and comments (managed with the django comments framework).
I thought to store the parent element of every note (so I can place it later) and store the name of the rows and columns like CSV strings. Is that a good approach?
A screenshot of the current frontend: http: //ur1. ca/4zn4h
Update: I almost forgot, the frontend has been done with jQuery Sortables (so the user can move the note around as he likes) and CSS3.
You just need to model your domain (that is, debates that look like scrum boards) within Django. Think about it in plain English first, like this:
The has debates. These consist of criteria, organised in rows and columns in a specific order. This creates cells, which can have notes inside them.
Then you can set to work translating this into model classes. Don't worry too much about the fields they contain, the most important bit is the relationships (so the ForeignKey bits):
class Debate(models.Model):
title = ...
class Column(models.Model):
title = ...
order = ...
board = models.ForeignKey(ScrumBoard, related_name='columns')
class Row(models.Model):
title = ...
order = ...
board = models.ForeignKey(ScrumBoard, related_name='rows')
class Cell(models.Model):
column = models.ForeignKey(Column)
row = models.ForeignKey(Row)
class Note(models.Model)
text = ...
cell = models.ForeignKey(Cell)
That might be overly complex for what you need, though. I'm not an expert in the problem you're trying to solve? My suggestion, Django is quick – so start hacking, and give it a go, and if it's all wrong then you can go back a few steps, clean out your database and try again.
You might find it useful to play with South, which does database migrations for when you do things like add/remove/edit fields in your models.
How can I simply add new simple products incrementally to configurable products?
or do I still need to retrieve the 2 original arrays of the pre-defined configurable product (getConfigurableAttributesData and getConfigurableProductsData) first, append the new arrays and set them again? Is it worked for my case just as the first-time creation?
And if the new simple product owns a new attribute / attribute options, do I also need to create /edit the attribute first before adding?
Thanks in advance!
The API as it stands does not have the functionality to do this.
Your options are:
Extend the API. (Hours of fun)
Do it with Magento methods in your own module or standalone code that includes Mage.php.
SQL script mixed in with your existing API code.
Buy someone's module - (Hope your German is good)
The approach you take also depends on your SKU naming scheme, if you have a simple BASECODE-SIZE-COLOUR type of scheme then the SQL option can work a treat, and in next to no time, but will be heavily scorned on by Magento evangelists.
That means you are probably going to have to write your own code. Here is a very useful site that should help get you started:
http://www.ayasoftware.com/
As well as being able to import configurables (by a variety of means including SQL) there are also snippets of code useful for updating superattribute price differentials. No readymade complete solution, but, you may need to roll your own anyway depending on your SKU naming scheme.
Whilst you are at it you may also want to write some code to find simple products that are not hooked up to anything when they should be, i,e. the ones with no visibility.
I have a category dedicated for exported goods , obviously , they will not be sold locally . so , how can I prevent customers who are from my country from ordering products that are meant only for exporting.. and showing an error message .. please help !
I would say that you will have to create a new product type. You'll need a new module (use Daniel's excellent kick-start extension: http://www.magentocommerce.com/magento-connect/Daniel+Nitz/extension/1108/modulecreator) and then have your model extend Mage_Catalog_Model_Product_Type_Simple.
Then, add a new attribute for your new product type to capture Allowed Countries, and implement the isSalable method in your Model to check for Allowed Countries.
This is not trivial, but it should be the right approach. The guys at Inchoo (who write a great blog) have a good tutorial on the process: link text and in fact they've provided the shell of the module.
Good luck!
JD