I'm a beginner in Python and Django.
I have installed django-oscar. Then I Configured it and started the server, it works.
Now, I don't understand how to add a product?
At the dashboard there is a button Create new product. But in order to add new product it asks to select product class and I can not find any product class in the given dropdown options.
Provide me a demo example of how to add product in django-oscar.
You need to be logged in as a superuser and go to the store/dashboard URL
DO NOT ADMINISTER THIS FROM THE NORMAL DJANGO ADMIN CONSOLE (even though that answer was accepted?)
Here is an example of what this looks like in the included sandbox app
You need to add a category, product type, and partner and only then can you begin adding real products
Check out this commit - it hasn't been merged to the Oscar's master yet, but should give you an idea on how you can create products programmatically, for instance when importing data.
https://github.com/ArtS/django-oscar/blob/3f9abaf8d5c179c385b90dfa463a35ff9f92f73c/docs/source/recipes/importing_a_catalogue.rst
There is a separate page to administer product types, complete with a "Create new product type" button.
Using django-admin is not a good solution, you may be able to add product types and products through it, but you'll be missing out on any dashboard hooks into the normal process.
A look at the source code shows that whilst you may be able to add a product without a type (the FK is nullable), you may then experience other problems down the line as oscar expects only child products to have a null product_class.
#: None for child products, they inherit their parent's product class
product_class = models.ForeignKey(
'catalogue.ProductClass', null=True, on_delete=models.PROTECT,
verbose_name=_('Product Type'), related_name="products",
help_text=_("Choose what type of product this is"))
Definitely best to try to work with the system rather than around.
You have to add atleast one product class /admin/catalogue/productclass/
Related
I recently forked Saleor 2.9 for a web app I am building for an art gallery that wants to display their products for sale as well as give their artists some publicity. I want to be able to have a bunch of cards (like "our team" components) that pull data from an Artists table on the back-end that stores information about the artists' names, emails, origins, etc, and then display it on the front-end. I am struggling to see how to modify the models/DB to create a new "Artists" table with name, email, info, and then to create a manyToMany-like relationship with the products I've populated in the DC, giving the products a "created by" attribute. There are tons of models files throughout the /dashboard directory, and even when I make changes to the core models to create an artist class, I don't know how to get it to show on the dashboard so artists can be created/modified from there.
I would like to make it so that the client (non-technical) can add artists and have them show up on the artists page I will make, somewhat like products show up on their pages (but obviously I cannot create a new category "Artist" as artists cannot have prices or shipping as they are people; and there are other attributes I would want like email that a product cannot have, either. They are also different to staff on the website, so I cannot use the "staff management" functionality.)
I looked at this question but Saleor structure has changed since then, and that was a relatively minor attributal change to an existing class (User) as opposed to the creation and integration of a new class. I'm surprised that despite extensively searching for anything on how to do something as straightforward as create a new model there is little documentation and discussion online; I must be missing something.
Please help :) Thank you!
The django way to create new models, (and Saleor´s backend is django based) is:
You should create a new app on your store backend (the django part of saleor) with:
$ python manage.py startapp artist
Create your Artist model, with all the fields you want such as email, etc... in the file: artist/models.py.
Modify the Product model in the file product/models.py by importing the Artist models and adding a ForeignKey (for example) relationship to it.
Register the new artist app in your settings.py's "INSTALLED_APPS".
Run python manage.py makemigrations... (Check they include your changes to models)
Run python manage.py migrate.
That should be it. 'less I`m forgeting something, in which case, please post back when you have moved forward with this.
Notes:
You may want to back up your DB first.
Also when applying these migrations, django will ask you for a placeholder value for products which where in your DB before Product had an Artist field.
References:
django models
django migrations
I have a few forms that retrieve objects through a ForeignKey, e.g. Flight, Trip.
So, for example, when someone tries to create a new Trip, they can choose an Hotel from a dropdown.
My question is: how can we, on the Trip form, add an Hotel. Just like when using Django's own admin dashboard, where you get a plus sign, and you can add a new Hotel while creating a Trip.
Edit:
Hotel is a ForeignKey on the Trip model.
And I am using ModelForm.
The objective is that you can either choose an existing Hotel or create a new one while creating a Trip.
I think you are looking for forms.ModelChoiceField.
It is used this way:
hotel = forms.ModelChoiceField(
queryset=Hotel.objects.all() # or whatever queryset you want to use
# Rest of the configuration
)
If I'm not mistaken, it will create an Html Select tag having options with pk of each Hotel object as the value. To specify the inner text of each option, you have to define the following method for the Hotel class:
def __str__(self):
return self.name # or whatever needed
If you indeed were looking for this I have to discourage you from using it if you are building a production-grade website/app. A better (and obviously more elaborate) approach is to get the query set of Hotels, serialize them to JSON, create a card/row/widget for each hotel for the user to search and select. However, it is a quick and handy way of managing small projects.
I'm building my first Django app to manage multiple SaaS products.
This entails storing custom attributes for each Version of each Product.
For example, a new version of a Product is released that includes new configuration options that the earlier versions of the Product do not support.
I need to be able to keep track of those new values for each instance of the new Version.
I'm thinking I want the Admins to be able to add "custom fields" at the Product level by Version.
Looking for suggestions as to the best approach.
Thanks.
The common way of tracking model versions is to use django-reversion.
It sounds like each instance needs its own custom attributes. That means that changing the Models relating to Product and Version need not occur. This is good, because models can only change with the code (unless you get into dynamically generating Models which is usually not a good idea).
So, you need to be able to model attributes for each Product instance, regardless of Version. This should be a simple data modelling exercise, not necessarily related to Django.
A Product has a set of fields
A Product has a Version
A Product has a set of Attributes
This is quite easily modelled, depending on how you want to manage attributes.
class Version(models.Model):
version = models.CharField(max_length=10)
class ProductAttributes(models.Model):
name = models.CharField(max_length=64)
description = models.CharField(max_length=255)
# other fields as necessary
class Product(models.Model):
name = models.CharField(max_length=64)
version = models.ForeignKey(Version)
attributes = models.ManyToManyField(ProductAttributes, related_name='products')
That should be your modelling sorted in a very basic way. Now, let's create some instances.
v1 = Version(version='1.0.0')
v1.save()
hosted = ProductAttributes(name='Hosted', description='We host the apps!')
hosted.save()
shiny = ProductAttributes(name='Shiny', description='I like shiny')
shiny.save()
p = Product(name='Web Based Email', version=v1)
p.save()
p.attributes.add(hosted)
p.attributes.add(shiny)
p.attributes.all()
# shows shiny and hosted!
You can tweak the ModelAdmin for Product such that you can add ProductAttributes inline when adding or editing a Product. You can also have a separate ModelAdmin for ProductAttributes so you can create a list of known Attributes that can be applied to products at a later date.
There are two basic approaches for this.
Use a document based db (ie, "NoSQL") like Couch or Mongo. These have flexible schemas, so allow for multiple variations on a product.
Use the Entity Attribute Value (wikipedia) schema pattern. django-eav is an app that provides this.
Decide to go with sub-classes with each Product as each has a limited set of specific attributes that won't change much or at all over time. Thanks for all the great feedback. Learned a lot :-)
(All code is some kind of pseudocode, just for better reading
I have an Invoice model:
class Invoice(models.Model):
// many fields here
I need to attach some products (with price for unit, and quantity fields) to this invoice, so I made additional table:
class InvoiceProduct(models.Model):
product = models.ForeignKey
quantity = models.IntegerField
unit_price = models.DecimalField
invoice = models.ForeignKey(Invoice)
So, this is almost first question — «Could it be done better way?»
My second problem is, that in django admin I have manage these models by inlines:
Screenshot
But my customer wants otherwise. He wants one button (Add product) then pop-up windows appears, with fields:
product, quantity, unit price. He fills them, press OK. Then pop-up window closes and line with "product fields" appears in main form.
I suppose I need override admin form template? Or I need to write my own widget or smth like that?
Sorry for my English.
My suggestion for your customer's request
He wants one button (Add product) then pop-up windows appears, with fields: product, quantity, unit price. He fills them, press OK.
Do NOT use the django admin for this. Only use it for people who want to access the data almost directly. In my head I see it just one half step up from the database itself. This means it is not suitable for users rather than administrators.
Or I need to write my own widget or smth like that?
Yes
This one is driving me nuts right now. It was not happening before (even got screenshots I had to do for the user-manual since the customer required it).
I first noticed it on production server and then I checked and also happens in the dev server that comes with Django. The model appears on the main-page of the django admin, I can click it and it will display the list of point of sales. The problem comes whenever I want to edit an existing instance or create a new one.
I just click on the link (or put it on the bar) and it just hangs.
class PointOfSaleAdmin(admin.ModelAdmin):
list_display = ('id','business', 'user', 'zipcode', 'address','date_registered')
list_filter = ('business',)
filter_horizontal = ('services',)
admin.site.register(models.PointOfSale, PointOfSaleAdmin)
That's the registration of the model. All models are registered in the admin application and the user to test this is a super user. The model is:
class PointOfSale(models.Model):
user = models.ForeignKey(User)
zipcode = models.ForeignKey(Zipcode)
business = models.ForeignKey(Business)
services = models.ManyToManyField(Service,
verbose_name='available services')
date_registered = models.DateField(auto_now_add=True)
address = models.CharField(max_length=300)
Plus a few methods that shouldn't really matter much. Plus, last time before this that I tested the admin was right after I created all those methods, so it shouldn't matter on this.
The administrator very very rarely has to access this page. Usually it's just listing the PoS, but it still bothers me. Any idea of why it could be hanging? All other models are working just fine.
This is happening on both Django 1.2.5 and 1.3
EDIT:
I modified the timeout limits. It IS working, but somehow it takes several minutes for it to actually happen. So, there is something in the background that is taking ages. I don't understand how come it happens only for this model and it happens in different environments (and with small datasets)
I almost feel like slapping myself. My fault for not sleeping for so long.
The problem is that the zipcode list is pretty big (dozens of thousands) and the foreign key field is loaded as an html select tag, which means it loads every single entry. It's an issue with how much data there is simply.
Now I wonder how to control the way the foreign key is displayed in the admin. Anyone could help with that?
In your admin.py file, under the appropriate admin class, set
raw_id_fields = ('zipcode',)
This will display the zipcode's PK instead of a dropdown.
Is there a reason that you are setting up zipcode as it's own model instead of using a CharField or an actual zipcode modelfield?
I just wanted to add that another option here is creating a read_only_fields list. In cases where there is a relationship to a model with a large number of choices(in my case a rel table cataloging flags between a large number of users and discussion threads) but you don't need to edit the field. You can add it to the read_only_fields list will just print the value rather than the choices.
class FlaggedCommentsAdmin(ModelAdmin):
list_display = ('user', 'discussion', 'flagged_on')
readonly_fields = ('user', 'discussion')
For people still landing on this page: As Mamsaac points out in his original post, the timeout happens because django tries to load all instances of a ForeignKey into an html-select. Django 2 lets you add an auto-complete field which asynchronously lets you search for the ForeignKey to deal with this. In your admin.py do something like this:
from django.contrib import admin
from .models import Parent, Child
#admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
# tell admin to autocomplete-select the "Parent"-field 'children'
autocomplete_fields = ['children']
#admin.register(Child)
class ChildAdmin(admin.ModelAdmin):
# when using an autocomplete to find a child, search in the field 'name'
search_fields = ['name']
Have you tried checking the apache logs (if you're using apache obviously) or any other HTTP server related logs? That might give you an idea of where to start.
That's the only model that is affected? You mentioned methods on the model. Try commenting out those methods and trying again (including the __unicode__ method), just to see if they somehow affect it. Reduce everything down to the bare minimum (as much as possible obviously), to try and deduce where the regression started.
Try to monitor server resources when you request this page. Does CPU spike dramatically? What about network I/O? Could be a database issue (somehow?).
Sorry this doesn't really answer your question, but those are the first debugging techniques that I'd attempt trying to diagnose the problem.