I'm pretty new to Django and Python. I'm trying to create some "category-dependent" models.
I have a Product model and i want to have category-dependent atributes. Example:
If i select "Permanent Dyes" in the category of my product i want to have specific atributes for my user to fill.
I don't want to create different models for every type of product i'm going to manage.
Is there any workaround to do this and keep using the django-admin?
Thanks in advance!
Model inheritance seems like it would help in this situation. Using it, you can have an abstract Product base class and then use Meta to add different product-dependent characteristics you need. It may require different models, but you would only need to add the attributes you needed, like below
class Product(models.Model):
....
class ProductA(Product):
class Meta:
....
This will allow you to have general properties in the Product class, such as price, etc., but use the subclass as a way to distinguish between different products.
Hope that helped in some way!
Related
I'm wondering what is the best way to represent the models, because there are some fields in common and others that change according to the category.
Example: Common fields: (title, author, content, photo, references)
Category and its specific fields:
Biography (birth data, death data, occupation)
Commemorative date (data, description)
Music (artist, album, year, musical style)
The best would be to create a generic model with common fields and others inherit from it (abstract models)?
Create a model for each category, ie repeating the common fields?
Create a single model with the common fields and have a category field that when selected would display the category-specific fields in django-admin? In that case, I suppose it would be done with jquery? Any references? There is nothing the material has on this on the internet.
Note: All user interaction to register is in django-admin.
From the docs:
Often, you will just want to use the parent class to hold information that you don’t want to have to type out for each child
model. This class isn’t going to ever be used in isolation, so
Abstract base classes are what you’re after.
If you’re subclassing an existing model (perhaps something from another application entirely) and want each model to have its own
database table, Multi-table inheritance is the way to go.
So if you don't want the parent class to have it's own table, abstract model is the way to go.
For a given model :
class SignUp:
....
I have seen two ways of registering the model to admin in few tutorials.
one is simply using
admin.site.register(SignUp)
and other is:
class signUpAdmin(admin.ModelAdmin):
class Meta:
model=SignUp
admin.site.register(SignUp, SignUpAdmin)
If I am correct, the second way is handy when we want to customize the admin (display, sorted order etc). but if one is not interested in that, then both serve the same purpose correct?
From the docs:
...you can register the model class without providing a ModelAdmin
description.
So admin.site.register(SignUp) would be the same as,
class signUpAdmin(admin.ModelAdmin):
pass
admin.site.register(SignUp, signUpAdmin)
Yes, that's correct.
The first one is the 'out-of-the-box' solution, while the second one is needed when you want to do more fancy stuff (for example editing a model that has a 1 to n relation).
I have the following (simplified) models:
class Structure(models.Model):
name=models.CharField(max_length=100, unique=True)
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
Each model, also has a builtFrom field, which shows what the item is built from, for example:
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
builtFrom=models.ForeignKey(Structure)
However, builtFrom can be populated from either a Unit type, or a Structure type. Is there an easy way to represent this in my models?
The only thing I can think of is to have a separate model, like so:
class BuiltFromItem(models.Model):
structure=models.ForeignKey(Structure)
unit=models.ForeignKey(Structure)
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
builtFrom=models.ForeignKey(BuiltFromItem)
And then have one of the BuiltFromItem fields just be null. Then, when I need the data, figure out whether it is a structure or unit that it is built from. Is there a better solution for this?
You want what the Django docs refer to as a "generic relation". Support for them is built into Django.
Generic relation is probably the best approach, yet it can be a little problematic, if you're planning to manage such models via admin panel. You would then have to add a ModelInline to the models, that generic relation is pointing to, but as far as I know (correct me if I'm wrong), there's no convenient way of picking related object from the other side (from model, where relation is defined), other than choosing model class and manually typing instance primary key.
Picking the best solution actually depends on structure of your models and on what they have in common. Another idea I have, is to use Multi-table inheritance, by defining some BasicObject that is a parent object to Structure and Unit models:
class BasicObject(models.Model):
name=models.CharField(max_length=100, unique=True)
#other common data
builtFrom=models.ForeignKey('BasicObject')
class Structure(BasicObject):
#data specific to Structure
class Unit(BasicObject):
#data specific to Unit
Now all Structure and Unit object will also be BasicObject instances, and you will be able to populate builtFrom field with proper BasicObject instance. It makes queries more expensive, because data is divided into two diffrent tables, so you should consider if this approach is beneficial in your case.
Using django, say I have model classes A and B, representing different types of Companies. Each Company may have multiple Users associated with it. Obviously I'd like to use django's User model, to get the login, etc. goodness. How would I go about doing that? Would I add a UserProfile that has two foreign keys, one to A and one to B (and the one that isn't null points to the company that the User works for)? Or is there another way?
thanks!
Use inheritance: define a superclass for Company, with the common fields, and then inherit that class and add the stuff ClassACompany and ClassBCompany need.
This way the UserProfile can have a foreign key to Company. If you need to get from the company to the specific type of company, you can do that as described in the docs.
why dont you just have one class for Company? that'll make your system much, much simpler.
you can then have specific fields inside Company that will let you determine whether it's of type A or B (what's the difference anyway?)
If you really must have different fields inside CompanyA and CompanyB then you can have them both derive from a common Company class which your ForeignKey will point to.
You would need to reference the Company model, and if need be, subclass Company with CompanyA and CompanyB. For simplicity, your Company class could have a type attribute with possible A and B values, then you could avoid subclassing.
Here's the deal:
I got two db models, let's say ShoppingCart and Order. Following the DRY principle I'd like to extract some common props/methods into a shared interface ItemContainer.
Everything went fine till I came across the _flush() method which mainly performs a delete on a related object set.
class Order(models.Model, interface.ItemContainer):
# ...
def _flush(self):
# ...
self.orderitem_set.all().delete()
So the question is: how do I dynamically know wheter it is orderitem_set or shoppingcartitem_set?
First, here are two Django snippets that should be exactly what you're looking for:
Model inheritance with content type and inheritance-aware manager
ParentModel and ChildManager for Model Inheritance
Second, you might want to re-think your design and switch to the django.contrib content types framework which has a simple .model_class() method. (The first snippet posted above also uses the content type framework).
Third, you probably don't want to use multiple inheritance in your model class. It shouldn't be needed and I wouldn't be surprised if there were some obscure side affects. Just have interface.ItemContainer inherit from models.Model and then Order inherit from only interface.ItemContainer.
You can set the related_name argument of a ForeignKey, so if you want to make minimal changes to your design, you could just have ShoppingCartItem and OrderItem set the same related_name on their ForeignKeys to ShoppingCart and Order, respectively (something like "item_set"):
order = models.ForeignKey(Order, related_name='item_set')
and
cart = models.ForeignKey(ShoppingCart, related_name='item_set')