Django-carton work with two Product models - python

I am using Django-carton (https://github.com/lazybird/django-carton) and I wonder if it is possible to associate more than one model as a Product model.
Right now, I have a base class Product which I registered as my product model and I inherited Pub and Restaurant from it. The problem I face is, cart.show() basically returns all product objects in the cart which only have products attributes and not Pub's or Restaurant's, and I can not distinguish which one is Pub and which one is Restaurant.

In your base model you can define method get_type without implementation, and in inherited classes, implement it, for example:
class Product(models.Model):
...
def get_type(self):
pass
class Meta:
...
abstract = True
class Pub(Product):
...
def get_type(self):
return 'pub'
class Restaurant(Product):
...
def get_type(self):
return 'restaurant'
If you know the type of an instance, you can easily access needed attributes.
Or you can use just isinstance built-in function:
if isinstance(obj, Pub):
# Your logic here

Related

Django model inheritance with proxy classes

I've got proxy classes which have been created mainly to implement custom filtering, but there are some other fairly small custom methods as well, and they will be expanded to provide other custom logic as well.
So say I have models:
class Videos(models.Model):
title = models.CharField(max_length=200)
publisher = models.Charfield(max_length=100)
release_date = models.DateField()
class Superheroes(Videos):
objects = SuperheroesManager()
class Meta:
proxy = True
class Recent(Videos):
objects = RecentManager()
class Meta:
proxy = True
and model managers:
class SuperheroesManager():
def get_queryset(self):
return super().get_queryset().filter(publisher__in=['Marvel','DC'])
class RecentManager():
def get_queryset(self):
return super().get_queryset().filter(release_date__gte='2020-01-01')
On the front end a user may pick a category which corresponds to one of the proxy classes. What would be the best way to maintain a mapping between the category which is passed to the view and the associated proxy class?
Currently I have an implicit dependency whereby the category name supplied by the front end must be the same as the proxy class name, allowing for a standard interface in the view:
def index(request, report_picked)
category = getattr(sys.modules[__name__], report_picked)
videos = category.objects.all()
I'd like to move away from this implicit dependency, but not sure what the best way would be.
I wouldn't want to maintain a dictionary and can't use a factory method either as that should return a fully initialised object whereas I just need the class returned.
What would be the best way to implement this?
I've decided to set the category name used by the front end as a class variable:
class Superheroes(Videos):
category = 'superheroes'
objects = SuperheroesManager()
class Meta:
proxy = True
And so the view just loops through all the models, and returns the model whose category matches the provided value from the front end:
from django.apps import apps
def index(request, report_picked):
for model in apps.get_models():
try:
print(f"Report picked: {report_picked}, model: {model.name}")
if model.category == report_picked.lower():
category = model
break
except AttributeError:
pass
I'd be curious to know if there is any better alternatives though.

Passing instance method result to class attribute

Let's say I have two models, the first referencing a third User model:
class Parent(models.Model):
user = models.ForeignKey(User)
...
class Child(models.Model):
parent = models.ForeignKey(
Parent,
limit_choices_to={'user': get_user()}
)
def get_user(self):
return self.request.user
I want to limit choices for the child model to instances bound to current user. One way to do it would be to pass the request to the form class and solve it inside __init__, but it present's other limitations. Is there a way to do this inside the model class, kind of like in the example above?

Creating parent model that all models will inherit from in Django

I am attempting to create a model class that all models will inherit from when they are created (in Django). I want any model class, with any attributes to be able to inherit from this class and read from the appropriate database table.
I know I am going need to use **kwargs and .setattr() at some point but am unclear as to where I even start. I am also going to try to recreate .all(), .filter() and .get() with in that class that all other methods that inherit this class can access.
This is what I have so far:
import sqlite3
class Model:
def __init__(self):
pass
#classmethod
def all(self, **kwargs):
pass
#classmethod
def get(self):
pass
#classmethod
def filter(self):
pass
###don't touch the code for these
class Users(Model):
pass
class Stocks(Model):
pass
How can I go about the initialization of this class?
It looks like you're trying to insert an abstract base class for your models.
Basically, what you've got there is correct, except you're missing
from django.db.models import Model
class MyModelBase(Model):
class Meta:
abstract = True
# ... The fields and methods I want all my models to inherit.
Then rather than making your models inherit from django.db.models.Model, they should inherit from MyModelBase.

How to create mixin to use #property in classes

I've got the following class
class UserProfile(models.Model):
# ...
#property
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in UserProfile._meta.fields]
I want to use that property on all my classes. So I want to make a mixin.
class HelperMixin(object):
#property
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in UserProfile._meta.fields]
Trouble is, the property has class specific code in it. How do I generalize the code to work in other classes?
And what is the difference when I use it like this:
class UserProfile(models.Model, HelperMixin)
vs. like this
class UserProfile(HelperMixin, models.Model)
Use self._meta.fields, class members are available on instances as well:
class HelperMixin(object):
#property
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in self._meta.fields]
The differense between class UserProfile(models.Model, HelperMixin) and class UserProfile(HelperMixin, models.Model) lies in the MRO (method resolution order). It would seem natural to have the mixin before the base class, but as long as the base and the mixin does not have members with the same name it makes no difference.

django generic one-to-one relations, with cascading deletes

I'm trying to emulate an inheritance model using django's generic relations. So far, this is what I've come up with:
class Base(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
... other stuff
class Meta:
unique_together = ("content_type", "object_id")
class SubClass1(models.Model):
... properties for this class
_base = generic.GenericRelation(Base)
#property
def base(self):
return self._base.all()[0]
From what you can see here (hopefully, at least), the SubClass1 should have a one-to-one relationship with Base, which is why I went through all the work of creating that _base field and then covering it with the base property. Having that generic relation will automagically wire up cascading deletes, which is what I want (and I have a post-delete signal that will wire up the delete from the other direction).
There could be any number of subclasses off of Base, and the thing that makes me feel gross is having to copy&paste the _base and its covering property. I've also got a custom object manager that goes with this, and potentially other things that essentially should all behave the same within each subclass of Base.
Is there a good way to go about encapsulating this common functionality so I don't have to copy&paste it for each sub class?
Why not have a BaseSubClass, and then inherit from that. So based on your example:
class BaseSubClass(models.Model):
_base = generic.GenericRelation(Base)
class Meta:
abstract = True
#property
def base(self):
return self._base.all()[0]
class SubClass1(BaseSubClass):
# fields

Categories