My Django project has models ShopType and ShopItem. For each ShopType object I create, I want to associate — not a single ShopItem object — but a subclass of ShopItem. Basically, I want a model type in Django that is not a TextField or an ImageField or the like, but a ModelField.
Example: Using the Django admin interface, I create a new instance of ShopType called CheeseShop. This in turn creates a new Model called Cheese which inherits all of its behavior from ShopItem. If I go to the main page of my Django admin site, there's now a new link called "Cheeses", and I can create a bunch of Cheeses as I please.
Of course, I suspect that's not actually possible: If I create — say — PetShop, I wouldn't just have to add a new record to the database, I'd have to augment the database schema itself to include Pets (along with registering the new Pet Model with the admin interface and probably some other complicated things I haven't thought of yet).
But maybe there's an existing Django solution for this pattern? Or maybe there's a completely different, better-suited approach to the problem that might achieve the same effect?
Any thoughts?
Related
I am working on a project where I need to have 3 types of Users.
Admin
Vendor
Customer
My first approach to this problem was to define all models by sub-classing the AbstractUser model
class Customer(AbstractUser):
pass
class Vendor(AbstractUser):
pass
so the question is do i need to craete a UsermManager for every usertype model ?
As I said into a comment, the best way to achieve what you want is to use the Multi Table Inheritance paradigm in Django. It defines OneToOne relations underneath so you could do it on your own.
Extending the User model is also explained HERE (official Django documentation) and it is done the way I told you (with OneToOne relations).
Django noob here - I was recently pointed to django-all-auth for registering/handling users, which I'm finding awesome in its near instant setup.
However I'm stumbling at trying to implement multiple user profile models. In reading other answers I've found this to be the closest answer thus far, but not really what I need.
When coding my own basic registration the user would select an account type (basic, pro, elite for example - each being their own profile model). Depending on the link selected the signup form would display both the generic User registration form as well as the profile form of the type chosen by the user.
I know I can go so far as to completely customize all-auth and make something like this work, but I'm hoping to be pointed in a direction that involves less wrecking of the original app. I've thought about having user redirected after signup to choose a profile type, but that seems to be a lot of extra steps.
Thanks for the help!
To extend the basic user class, just subclass AbstractUser. You can find that in the docs. With this you can add the fields your basic user is missing.
Now, you want several types of profiles with different fields, or perhaps the same fields but adding new fields every time.
You can create something like:
class ProfileBase(models.Model):
user=models.OneToOneField(User)
class ProfilePro(ProfileBase):
pro_field=models.SomeField(Foo)
#You can extend ProfilePro here if you want it to include the pro_field
class ProfileElite(ProfileBase):
elite_field=models.someField(Bar)
Once you have these models creating the forms should be easy.
Be aware, when you subclass this way django creates 1 table per model, including on the subclass table only the new fields. This makes necessary a join per level of inheritance so try not to abuse that.
There is a second way to use inheritance:
class ProfileBase(models.Model):
user=models.OneToOneField(User)
class Meta:
abstract=True
If you define the base class as abstract you won't have a table for it, so you can't create objects for that model, but each of your subclasses will be on it's own table. If you do it this way you may need extra logic to handle cases when user changes of type of profile (i.e. went from pro to elite).
To keep this separated from django-allauth, just finish the registration (create a form and in your settings define ACCOUNT_SIGNUP_FORM_CLASS to override all-auth default with your basic info + pick a profile type form) and once your user is logged in, redirect them to their profile to finish the process.
I have some issue with Django CMS 3.0 plugin model copy_relations function.
Example from documentation
def copy_relations(self, oldinstance):
for associated_item in oldinstance.associated_item.all():
# instance.pk = None; instance.pk.save() is the slightly odd but
# standard Django way of copying a saved model instance
associated_item.pk = None
associated_item.plugin = self
associated_item.save()
is not working and CMS is only modifying instance of plugin model. In this example I need to add associated_item.id = None for it to work.
This is not my first Django CMS project, but is first in 3.0. In previous versions I did follow documentation and everything was ok, but not this time.
The question is: is the documentation not up-to-date or I did something wrong on the way when creating models?
edit:
Here is where I found how to make Django CMS to save a copy of model instance:
Due to how inheritance works, you have to set both ``pk`` and ``id`` to None
I need to do this for all models with copy_relations, and I want to know why is this required.
Obviously in your case associated_item points to a model which inherits from another model. There are two types of model inheritance in Django: abstract and multi-table.
In the case of abstract inheritance, the base model is abstract, i.e. it is not in the database and just serves as a template for the models which inherit from it.
In the case of multi-table inheritance, all of the models are in DB, with submodels linked to the base model via a ForeignKey.
For regular models .pk and .id are one and the same thing (you can even check it with my_model.pk is my_model.id), while for multi-table submodels .id is the id field of the base model, and .pk is the ForeignKey used to connect the submodel to the base model. In fact, the numeric value of .pk and .id is still the same (because .pk points to .id), but nonetheless they are two separate columns in the DB. In my opinion this Django design decision is somewhat inconsistent, but that's what we have.
That's why you need to set both fields to None for Django to lose track of the model and see it as a new model instance.
I have the Models with fields. basically i want to do the CRUD opertions like in admin.I have used
Class Meta
model = Modelname
Now my create part is done by defining function create_from.
I want to know that do i need to create separate functions to EDIT , DELETE , READ all Model data. Or i can use buildin admin functions for that. because all the functionality is already on admin side.
See https://docs.djangoproject.com/en/1.3/ref/class-based-views/ - especially the Editing Mixins on that page.
I want to make the following modification to the Django framework.
I want it to create a "deleted" field for each model I create.
I want it to be checked as deleted when I delete it from the admin page instead of being physically deleted.
I do not want these records checked as deleted to be listed.
I'm new to Django, I'm seeing if I can do what I want to do with it easily. I need this change because it's the way we currently work.
So far these are the changes I have made, I would like to understand how the whole Django framewok works inside but I'm so far from that, is there any documentation online which explains clearly how the inside framework parts/files/modules/classes work together, the specific role of each one, etc
In the base.py file, in the modelbase class, below this code,
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)
I added,
from django.db import models
new_class.add_to_class('deleted', models.BooleanField())
When it creates a model it adds the "deleted" field to it.
In the base.py file, in the save method, I changed what it was there for
self.deleted = True
self.save()
So, now it check as deleted a record instead of physically delete it.
Now what I want is those records not to be listed.
I don't understand why you're modifying the framework code instead of putting your deleted field in a model base class that all of your models extend from.
Nevertheless, a nice way to filter those records out would be to add a custom manager to the model (or your base model class, if you choose to create one). To this manager, override the get_query_set method as described here. In your overridden method, add a exclude(deleted=True) filter.
Take a look at the Django-logicaldelete app, You just inherit your models from their provided Model class and you get Logical delete for all of them.
It comes with an adminModel as well so you can manage logically deleted models there too.
Override the delete() method in your model class, set the deleted attribute there
Create a custom manager which will filter by deleted attribute and set it as the default one (objects = MyDeletedManager)