I have a product class in the Django model. Over there are product name, category and department name (foreign key).
So I want to create an automatic code generator that will generate automatically like 2 or 3 alphabets as category name and 3 alphabet department name and 6 digits number; for example: COM-ELC-000001
class Item(models.Model):
item_name = models.CharField(max_length=255, blank =True)
description = models.CharField(max_length=255, blank=True, null=True)
item_choice = (
('IT','IT'),
('Electronics', 'Electronics'),
)
item_type = models.CharField(max_length=255, blank =True, choices = item_choice )
code = models.CharField(unique=True, max_length=255)
unit = models.CharField(max_length=255, blank=True, null=True)
company = models.ForeignKey(Company, on_delete = models.SET_NULL, null =True,blank=True)
department = models.ForeignKey(Department, on_delete = models.SET_NULL,null= True, blank=True)
In Your Models
class Item(models.Model):
item_name = models.CharField(max_length=255, blank =True)
description = models.CharField(max_length=255, blank=True, null=True)
item_choice = (
('IT','IT'),
('Electronics', 'Electronics'),
)
item_type = models.CharField(max_length=255, blank =True, choices = item_choice )
code = models.CharField(unique=True, max_length=255)
unit = models.CharField(max_length=255, blank=True, null=True)
company = models.ForeignKey(Company, on_delete = models.SET_NULL, null =True,blank=True)
department = models.ForeignKey(Department, on_delete = models.SET_NULL,null= True, blank=True)
def save(self, **kwargs):
code = "%s %s" % (self.item_name[:3], self.item_choice)
super(Item, self).save(**kwargs)
Related
I have model name Movie which have many-to-many Relation with Actor Table. Actor Table is further many-to-many relation with Celebrity-Role.
My question is i need only unique values on the base of roles Like Actors who's role is Director they show in Movie Table field with Director and only directors should be there and so on.
i share my models please have a look.
class CelebrityRole(models.Model):
CELEBRITY_CHOICES = (
('Actor', 'Actor'),
('Producer', 'Producer'),
('Writer', 'Writer'),
('Director', 'Director'),
)
role = models.CharField(max_length=8,
choices=CELEBRITY_CHOICES)
def __str__(self):
return self.role
class Actor(models.Model):
GENDER = (
('Male', 'Male'),
('Female', 'Female'),
)
name = models.CharField(max_length=200)
rank = models.CharField(max_length=5, default=0)
gender = models.CharField(max_length=6, choices=GENDER)
avatar = models.ImageField(upload_to='CelebrityGallery/',
blank=True)
description = models.TextField(blank=True)
birth_place = models.CharField(max_length=200, blank=True)
dob = models.DateField(auto_now=False, auto_now_add=False)
height = models.CharField(max_length=20)
is_married = models.BooleanField(default=False)
movies = models.ManyToManyField(
'movies.Movie', related_name='movies', blank=True)
celebrity_role = models.ManyToManyField(CelebrityRole)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Here is my Movie Table
class Movie(models.Model):
title = models.CharField(max_length=200)
year = models.CharField(max_length=25, blank=True)
description = models.TextField(blank=True)
released = models.CharField(max_length=25)
runtime = models.CharField(max_length=25)
language = models.CharField(max_length=255)
country = models.CharField(max_length=100)
metascore = models.CharField(max_length=5, blank=True)
imdb_id = models.CharField(max_length=10, blank=False,
unique=True, default='tt3032400')
imdb_rating = models.CharField(max_length=5, blank=True)
imdb_votes = models.CharField(max_length=100, blank=True)
budget = models.CharField(max_length=25)
box_office = models.CharField(max_length=25, blank=True)
imdb_original = models.BooleanField(default=False)
type = models.CharField(max_length=10, blank=True)
season = models.CharField(max_length=2, default=0,
blank=True)
episode = models.CharField(max_length=3, default=0,
blank=True)
poster_url = models.ImageField(upload_to='Posters/',
blank=True)
video_poster_url =
models.ImageField(upload_to='VideoPosters/', blank=True)
video_url = models.TextField(validators=[URLValidator()],
blank=True, max_length=2000)
genre = models.ManyToManyField(Genre,
related_name='genre_movies')
image_gallery = models.ManyToManyField(ImageGallery,
blank=True)
video_gallery = models.ManyToManyField(VideoGallery,
blank=True)
director = models.ManyToManyField(Actor,
related_name='director')
writer = models.ManyToManyField(Actor,
related_name='writer')
actors = models.ManyToManyField(Actor,
related_name='actors')
producer = models.ManyToManyField(Actor,
related_name='producer')
def __str__(self):
return self.title
I'm not sure how you can do it in your models.py. But you can use the filter method in your views.py when making queries to filter actors whose role is director, etc.
I have a product model. I need to autocomplete product name into input field. How can I code?
class Product(models.Model):
product_name = models.CharField(max_length=255)
product_detail = models.TextField(blank=True, null=True)
product_price = models.FloatField(blank=True)
category = models.CharField(max_length=30)
product_image = models.ImageField(upload_to='pictures/%Y/%m/%d/', max_length=255, blank=True, null=True)
product_amount = models.IntegerField(blank=True, null=True)
del_flag = models.BooleanField(default=False)
def __str__(self):
return self.product_name
I have the following 4 models in my program - User, Brand, Agency and Creator.
User is a superset of Brand, Agency and Creator.
A user can be a brand, agency or creator. They cannot take on more than one role. Their role is defined by the accountType property. If they are unset (i.e. 0) then no formal connection exists.
How do I express this in my model?
User model
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
email = models.EmailField(max_length=255, null=True, default=None)
password = models.CharField(max_length=255, null=True, default=None)
ACCOUNT_CHOICE_UNSET = 0
ACCOUNT_CHOICE_BRAND = 1
ACCOUNT_CHOICE_CREATOR = 2
ACCOUNT_CHOICE_AGENCY = 3
ACCOUNT_CHOICES = (
(ACCOUNT_CHOICE_UNSET, 'Unset'),
(ACCOUNT_CHOICE_BRAND, 'Brand'),
(ACCOUNT_CHOICE_CREATOR, 'Creator'),
(ACCOUNT_CHOICE_AGENCY, 'Agency'),
)
account_id = models.ForeignKey(Brand)
account_type = models.IntegerField(choices=ACCOUNT_CHOICES, default=ACCOUNT_CHOICE_UNSET)
class Meta:
verbose_name_plural = "Users"
def __str__(self):
return "%s" % self.email
Brand model
class Brand(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=255, null=True, default=None)
brand = models.CharField(max_length=255, null=True, default=None)
email = models.EmailField(max_length=255, null=True, default=None)
phone = models.CharField(max_length=255, null=True, default=None)
website = models.CharField(max_length=255, null=True, default=None)
class Meta:
verbose_name_plural = "Brands"
def __str__(self):
return "%s" % self.brand
Creator model
class Creator(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
first_name = models.CharField(max_length=255, null=True, default=None)
last_name = models.CharField(max_length=255, null=True, default=None)
email = models.EmailField(max_length=255, null=True, default=None)
youtube_channel_username = models.CharField(max_length=255, null=True, default=None)
youtube_channel_url = models.CharField(max_length=255, null=True, default=None)
youtube_channel_title = models.CharField(max_length=255, null=True, default=None)
youtube_channel_description = models.CharField(max_length=255, null=True, default=None)
photo = models.CharField(max_length=255, null=True, default=None)
youtube_channel_start_date = models.CharField(max_length=255, null=True, default=None)
keywords = models.CharField(max_length=255, null=True, default=None)
no_of_subscribers = models.IntegerField(default=0)
no_of_videos = models.IntegerField(default=0)
no_of_views = models.IntegerField(default=0)
no_of_likes = models.IntegerField(default=0)
no_of_dislikes = models.IntegerField(default=0)
location = models.CharField(max_length=255, null=True, default=None)
avg_views = models.IntegerField(default=0)
GENDER_CHOICE_UNSET = 0
GENDER_CHOICE_MALE = 1
GENDER_CHOICE_FEMALE = 2
GENDER_CHOICES = (
(GENDER_CHOICE_UNSET, 'Unset'),
(GENDER_CHOICE_MALE, 'Male'),
(GENDER_CHOICE_FEMALE, 'Female'),
)
gender = models.IntegerField(choices=GENDER_CHOICES, default=GENDER_CHOICE_UNSET)
class Meta:
verbose_name_plural = "Creators"
def __str__(self):
return "%s %s" % (self.first_name,self.last_name)
Agency model
class Agency(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=255, null=True, default=None)
agency = models.CharField(max_length=255, null=True, default=None)
email = models.EmailField(max_length=255, null=True, default=None)
phone = models.CharField(max_length=255, null=True, default=None)
website = models.CharField(max_length=255, null=True, default=None)
class Meta:
verbose_name_plural = "Agencies"
def __str__(self):
return "%s" % self.agency
Update:
So I've whittled it down to this bit here in the model:
ACCOUNT_CHOICE_UNSET = 0
ACCOUNT_CHOICE_BRAND = 1
ACCOUNT_CHOICE_CREATOR = 2
ACCOUNT_CHOICE_AGENCY = 3
ACCOUNT_CHOICES = (
(ACCOUNT_CHOICE_UNSET, 'Unset'),
(ACCOUNT_CHOICE_BRAND, 'Brand'),
(ACCOUNT_CHOICE_CREATOR, 'Creator'),
(ACCOUNT_CHOICE_AGENCY, 'Agency'),
)
account_type = models.IntegerField(choices=ACCOUNT_CHOICES, default=ACCOUNT_CHOICE_UNSET)
limit = models.Q(app_label='api', model='Brand') | \
models.Q(app_label='api', model='Creator') | \
models.Q(app_label='api', model='Agency')
content_type = models.ForeignKey(ContentType, limit_choices_to=get_content_type_choices(), related_name='user_content_type')
content_object = GenericForeignKey('content_type', 'email')
If account_type = 1 then link to brand model
If account_type = 2 then link to creator model
If account_type = 3 then link to agency model
How do I accomplish this? Getting this error:
File "/Users/projects/adsoma-api/api/models.py", line 7, in <module>
class User(models.Model):
File "/Users/projects/adsoma-api/api/models.py", line 28, in User
content_type = models.ForeignKey(ContentType, limit_choices_to=get_content_type_choices(), related_name='user_content_type')
NameError: name 'get_content_type_choices' is not defined
Have you tried exploring Django's GenericForeignKey field?
class User(models.Model):
...
limit = models.Q(app_label='your_app_label', model='brand') |
models.Q(app_label='your_app_label', model='creator') |
models.Q(app_label='your_app_label', model='agency')
content_type = models.ForeignKey(ContentType, limit_choices_to=limit, related_name='user_content_type')
object_id = models.UUIDField()
content_object = GenericForeignKey('content_type', 'object_id')
You can access the User's brand/creator/agency by using the following notation:
User.objects.get(pk=1).content_object
This will be an instance of Brand/Creator/Agency as per the content_type.
https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericForeignKey
Update based on your comment
Re 1: Using email:
class User(models.Model):
...
email = models.EmailField(max_length=255, unique=True)
limit = models.Q(app_label='your_app_label', model='brand') |
models.Q(app_label='your_app_label', model='creator') |
models.Q(app_label='your_app_label', model='agency')
content_type = models.ForeignKey(ContentType, limit_choices_to=get_content_type_choices, related_name='user_content_type')
content_object = GenericForeignKey('content_type', 'email')
Note: Email can not be a nullable field anywhere if you follow this approach! Also this approach seems hacky/wrong since the email field is now declared in multiple places; and the value can change if you re-assign the content objects. It is much cleaner to link the GenericForeignKey using the discrete UUIDField on each of the other three models
Re 2: Using account_type field:
ContentType is expected to be a reference to a Django Model; therefore it requires choices that are Models and not integers.
The function of limit_choices_to is to perform a filtering such that all possible models are not surfaced as potential GenericForeignKey
class ContentType(models.Model):
app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), max_length=100)
objects = ContentTypeManager()
However, limit_choices_to does accept callables; so you can write a helper method that translates your account_type to the correct Model
I am not clear about how this transaltion should work; so I leave that to you.
Here is how I solve it, override the save method check your condition
tested on Django 3.2
CUSTOMER = [
('customer', 'customer'),
('supplier', 'supplier'),
]
class Customer(models.Model):
name = models.CharField(max_length=256, null=False, blank=False)
user_type = models.CharField(max_length=32, choices=CUSTOMER)
class SupplierOrder(models.Model):
price = models.FloatField(default=0)
supplier = models.ForeignKey(Customer, related_name='supplier', on_delete=models.CASCADE)
def save(self, *args, **kwargs):
supplier = get_object_or_404(Customer, id=self.supplier.id)
if supplier.user_type != 'supplier':
raise ValueError('selected user must be supplier')
super().save(*args, **kwargs)
I have question about Django query models. I know how to write simple query, but Im not familiar with LEFT JOIN on two tables. So can you give me some advice on his query for better understanding DJango ORM.
query
select
count(ips.category_id_id) as how_many,
ic.name
from
izibizi_category ic
left join
izibizi_product_service ips
on
ips.category_id_id = ic.id
where ic.type_id_id = 1
group by ic.name, ips.category_id_id
From this query I get results:
How many | name
0;"fghjjh"
0;"Papir"
0;"asdasdas"
0;"hhhh"
0;"Boljka"
0;"ako"
0;"asd"
0;"Čokoladne pahuljice"
0;"Mobitel"
2;"Čokolada"
And I have also try with his Django query:
a = Category.objects.all().annotate(Count('id__category',distinct=True)).filter(type_id=1)
But no results.
My models:
models.py
class Category(models.Model):
id = models.AutoField(primary_key=True)
type_id = models.ForeignKey('CategoryType')
name = models.CharField(max_length=255)
def __str__(self):
return str(self.name)
class Product_service(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=True, null=True)
selling_price = models.DecimalField(decimal_places=5, max_digits=255, blank=True, null=True)
purchase_price = models.DecimalField(decimal_places=5, max_digits=255, blank=True, null=True)
description = models.CharField(max_length=255, blank=True, null=True)
image = models.FileField(upload_to="/", blank=True, null=True)
product_code = models.CharField(max_length=255, blank=True, null=True)
product_code_supplier = models.CharField(max_length=255, blank=True, null=True)
product_code_buyer = models.CharField(max_length=255, blank=True, null=True)
min_unit_state = models.CharField(max_length=255, blank=True, null=True)
state = models.CharField(max_length=255, blank=True, null=True)
vat_id = models.ForeignKey('VatRate')
unit_id = models.ForeignKey('Units')
category_id = models.ForeignKey('Category')
If you culd help me on this problem.
You should add a related name on the category_id field like:
category_id = models.ForeignKey('Category', related_name="product_services")
so that in your query you can do:
a = Category.objects.all().annotate(Count('product_services',distinct=True)).filter(type_id=1)
and then you can access the individual counts as:
a[0].product_services__count
I am trying to use the "limit_choices_to" functionality in a Django OneToOneField where upstream of what I want to limit the choices on is another ForeignKey. The error I get in the admin with the way I have it set up is:
invalid literal for int() with base 10: 'Storage Array'
I assume this is because it is looking at the actual value in the column asset_type which is an integer foreign key. I need to be able to limit the choices based on a field value of the foreign key as opposed to the key value itself.
Basically what I am trying to accomplish is having the admin area (and other forms) only allow you to choose a valid asset type when adding a new asset. For example, if I am adding a "storage array" the upstream asset tied to it should only be allowed to be asset_type of storage array.
Here is my model:
from django.db import models
from localflavor.us.us_states import STATE_CHOICES
# Table of brand names of assets
class Brand(models.Model):
brand = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return self.brand
# Table of device types for assets, e.g. "Storage Array"
class Device(models.Model):
device_type = models.CharField(max_length=128, unique=True)
device_url_slug = models.SlugField(max_length=70, unique=True)
class Meta:
verbose_name = "device type"
verbose_name_plural = "device types"
def __unicode__(self):
return self.device_type
# Table of asset locations
class Location(models.Model):
site_name = models.CharField(max_length=128, unique=True)
site_nick = models.CharField(max_length=5, unique=True)
address_line_one = models.CharField(max_length=256)
address_line_two = models.CharField(max_length=256, null=True, blank=True)
address_city = models.CharField(max_length=32)
address_state = models.CharField(max_length=2, choices=STATE_CHOICES, null=True, blank=True)
address_zip = models.CharField(max_length=5)
def __unicode__(self):
return self.site_name
# Table of Environments, e.g. "Production"
class Environment(models.Model):
environment = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return self.environment
class Credentials(models.Model):
AUTH_CHOICES = (
('SSH', 'Standard SSH'),
('SSH-Key', 'SSH with Key-based login'),
('HTTP', 'Standard HTTP'),
('HTTPS', 'Secure HTTP'),
('API', 'API Based'),
('SNMP', 'SNMP Based'),
)
SNMP_VERSIONS = (
('v1', 'SNMP v1'),
('v3', 'SNMP v3'),
)
auth_method = models.CharField(max_length=32, choices=AUTH_CHOICES)
auth_username = models.CharField(max_length=32)
auth_password = models.CharField(max_length=32, null=True, blank=True)
auth_snmp_version = models.CharField(max_length=2, choices=SNMP_VERSIONS, null=True, blank=True)
auth_snmp_community = models.CharField(max_length=128, null=True, blank=True)
class Meta:
verbose_name = "credentials"
verbose_name_plural = "credentials"
def __unicode__(self):
return self.auth_method
class Asset(models.Model):
asset_name = models.CharField(max_length=128, unique=True)
asset_type = models.ForeignKey(Device)
brand = models.ForeignKey(Brand)
model = models.CharField(max_length=128)
serial = models.CharField(max_length=256)
location = models.ForeignKey(Location)
environment = models.ForeignKey(Environment)
datacenter_room = models.CharField(max_length=32, null=True, blank=True)
grid_location = models.CharField(max_length=32, null=True, blank=True)
mgmt_address = models.CharField(max_length=128)
notes = models.TextField(null=True, blank=True)
def __unicode__(self):
return self.asset_name
class StorageArray(models.Model):
OS_NAME_CHOICES = (
('Data OnTap', 'NetApp Data OnTap'),
)
OS_TYPE_CHOICES = (
('7-Mode', 'NetApp 7-Mode'),
('cDOT', 'NetApp Clustered'),
)
HA_TYPE_CHOICES = (
('Standalone', 'Standalone System'),
('HA Pair', 'HA Pair'),
('Clustered', 'Clustered'),
)
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'Storage Array'})
os_name = models.CharField(max_length=32, choices=OS_NAME_CHOICES, null=True, blank=True)
os_version = models.CharField(max_length=16, null=True, blank=True)
os_type = models.CharField(max_length=16, choices=OS_TYPE_CHOICES, null=True, blank=True)
array_ha_type = models.CharField(max_length=32, choices=HA_TYPE_CHOICES, null=True, blank=True)
array_partner = models.CharField(max_length=128, null=True, blank=True)
credentials = models.ForeignKey(Credentials, null=True, blank=True)
class Meta:
verbose_name = "storage array"
verbose_name_plural = "storage arrays"
def __unicode__(self):
return self.asset.asset_name
class SANSwitch(models.Model):
OS_NAME_CHOICES = (
('FabricOS', 'Brocade FabricOS'),
)
SWITCH_TYPE_CHOICES = (
('Standalone', 'Standalone Switch'),
('Director', 'Director'),
('Router', 'Multiprotocol Router'),
('Blade', 'Blade Chassis IO Module'),
)
SWITCH_ROLE_CHOICES = (
('Core', 'Core'),
('Edge', 'Edge'),
('AG', 'Access Gateway'),
)
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'SAN Switch'})
os_name = models.CharField(max_length=32, choices=OS_NAME_CHOICES, null=True, blank=True)
os_version = models.CharField(max_length=16, null=True, blank=True)
switch_type = models.CharField(max_length=32, choices=SWITCH_TYPE_CHOICES, null=True, blank=True)
switch_role = models.CharField(max_length=32, choices=SWITCH_ROLE_CHOICES, null=True, blank=True)
credentials = models.ForeignKey(Credentials, null=True, blank=True)
class Meta:
verbose_name = "san switch"
verbose_name_plural = "san switches"
def __unicode__(self):
return self.asset.asset_name
I fixed it all by myself!
It seems to translate further down a relationship you can make use of the double underscore notation that python/django has built in.
To fix my issue:
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'Storage Array'})
became:
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type__device_type': 'Storage Array'})