Simple Django model design concept...need input? - django

I have a simple product database with the following:
class Product(models.Model):
sku = models.CharField(max_length=200)
name = models.CharField(max_length=200)
price = models.CharField(max_length=200)
class meta:
abstract = True
class Shoe(Product): #inherits from product
size = models.CharField(max_length=200)
class Computer(Product): #inherits from product
cpu = models.CharField(max_length=200)
This leaves 2 tables in the DB...Shoe and Computer. Now what if I want to organize them by category? As in have a Category model with a nice human-readable name, an icon for displaying on the product drop-down menu, and suchlike. I'm lost! Shoe and Computer are different models...so how can one model (Category) organize them?
HALP?

Just put this into Product:
category = models.ForeignKey(Category, related_name='%(class)s_set')
You can learn more about foreign keys here.

Perhaps you could use Generic Foreign Keys
class Category(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
name = models.charField(max_length=50)
class Product(models.Model):
categories = generic.GenericRelation(Category)
I"m not quite sure what you had in mind for categories, but you can create new categories referencing any object, Computer or Shoe
shoe = Shoe.object.get(pk=1)
category = Category(content_object=shoe, name='tennis')
category.save()
category = Category(content_object=shoe, name='waterproof')
category.save()
shoe.catetories.all()

Related

Django add a field to a model based on another model

I have a model for a product:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
I want to have a separate model ProductFields:
class ProductFields(models.Model):
field_name = models.CharField()
field_type = models.CharField()
field_verbose_name = models.CharField()
field_max_length = models.IntegerField()
filed_null = models.CharField()
field_blank = models.BooleanField()
field_default = models.CharField()
...
So the idea is whenever I add new ProductField I want Product model to migrate that added field to its database.
For Example:
ProductFields.objects.create(field_name='description', field_type='CharField', field_verbose_name='Description', field_max_length=255, filed_null=True, filed_blank=True)
This should transform Product modal to:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
description = models.CharField(verbose_name="Description", max_length= 255, null=True, blank=True)
Please let me know if you have any idea how this can be done?
If you're looking for a way to create a dynamic model you can look into these suggestions.
HStoreField using django-hstore : https://django-hstore.readthedocs.io/en/latest/
JSONField: JSONField is similar to HStoreField, and may perform better with large dictionaries. It also supports types other than strings, such as integers, booleans and nested dictionaries.https://django-pgfields.readthedocs.io/en/latest/fields.html#json-field
Or you can use a NoSQL database (Django MangoDB or another adaptation)

DJANGO - Default filter in model

I have 3 models :
class Product(models.Model):
name = models.TextField()
class Company(models.Model):
name = models.TextField()
users = models.ManyToManyField('auth.User')
class Sales(models.Model):
product= models.ForeignKey(Product)
company= models.ForeignKey(Company)
seller = models.ForeignKey('auth.User')
My goal is to display the list of all products sold by the company of request.user so in my views I do :
Enterprise= Company.objects.filter(users=request.user)[0]
Products_sold = Sales.objects.filter(company=Enterprise)
But since I have a lot of views I'm wondering if there is a way to it directly in the model?
Your user should have company_set:
Products_sold = Sales.objects.filter(request.user.company_set.all()[0])

Django model - set up a "has_many_through" relationship

Looking for advice on setting up this model.
This job board app has Company, Location, and Job. They should have the following relationships:
A Company can have multiple locations
A Company can have multiple jobs
A Job can have only one Company
A Job can have multiple locations, BUT each Location must be valid for the job's Company
I'd like to create a model that reflects these relationships. I think something like this might work:
class Company(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
class Location(models.Model):
is_primary_location = models.BooleanField()
address = models.CharField(max_length=200)
company = models.ForeignKey(Company)
class Job(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company)
location = models.ForeignKey(Location)
But I would really like the "Job has Location(s) through Company" relationship to be enforced. The model doesn't enforce it; I think I'd have to filter the valid Locations when data is displayed, and I'd like to avoid that.
Thanks very much!
Take a look at ForeignKey.limit_choices_to.
This allows you to filter the available choices and is enforced in ModelForm. Since you already have the company foreign key in your Job model, you should be able to use that to filter the choices.
I ended up using https://github.com/digi604/django-smart-selects and wrote the model like this. I don't think limit_choices_to works in this case (according to other SO threads)
from smart_selects.db_fields import ChainedForeignKey
class Company(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
class Location(models.Model):
is_primary_location = models.BooleanField()
address = models.CharField(max_length=200)
company = models.ForeignKey(Company)
class Job(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company)
location = ChainedForeignKey(
Location,
chained_field="company",
chained_model_field="company",
show_all=False,
auto_choose=True
)

about multiple relations in django.models? noob here

this is my models.py
from django.db import models
# Create your models here.
class Leagues(models.Model):
LeagueName = models.CharField(max_length=200)
class Team(models.Model):
TeamName = models.CharField(max_length=200)
class LeagueTable(models.Model):
league = models.ForeignKey(Leagues)
team = models.CharField(max_length=200)
matches_played = models.IntegerField()
matches_won = models.IntegerField()
matches_drawn = models.IntegerField()
matches_lost = models.IntegerField()
points = models.IntegerField()
class FixtureTable(models.Model):
league = models.ForeignKey(Leagues)
fixture_date = models.DateField('Fixture Date')
team_one = models.CharField(max_length=200)
team_one_score = models.IntegerField()
team_two = models.CharField(max_length=200)
team_two_score = models.IntegerField()
in the "class FixtureTable", i want team_one and team_two to be linked to two differnt teams in "class Team" models. how to create multiple relations, or is it possible.
PS: this is purely a noob, with a little experience in programming, but no experience with either python or databases.
thankyou.
You can create as many ForeignKeys as you like to the same model. I suspect what's tripping you up is Django giving you an error saying that you need to specify a related name.
By default, Django creates an attribute on the opposite model of the form <model>_set. So in the following scenario:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team)
Django would add a related manager to Team as fixturetable_set. If you then did:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team)
team_two = models.ForeignKey(Team)
Django would attempt to add the same attribute twice and obviously fail. The fix is to specify a related_name, so each can have a unique related manager:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team, related_name='team_one_fixturetables')
team_two = models.ForeignKey(Team, related_name='team_two_fixturetables')
Then, everything will work fine. You can specify whatever you like for related_name as long as it's unique for the model.

django queryset for many-to-many field

I have the following Django 1.2 models:
class Category(models.Model):
name = models.CharField(max_length=255)
class Article(models.Model):
title = models.CharField(max_length=10, unique=True)
categories = models.ManyToManyField(Category)
class Preference(models.Model):
title = models.CharField(max_length=10, unique=True)
categories = models.ManyToManyField(Category)
How can I perform a query that will give me all Article objects that are associated with any of the same categories that a given Preference object is related with?
e.g. If I have a Preference object that is related to categories "fish", "cats" and "dogs", I want a list of all Articles that are associated with any of "fish", "cats" or "dogs".
Try:
preference = Preference.objects.get(**conditions)
Article.objects.filter(categories__in = preference.categories.all())
Article.objects.filter(categories__in=myPreferenceObject.categories.all())