Im working on a problem that requires 2 different models to have unique Ids. So that an instance of ModelA should never have the same id as a ModelB instance.
For example, What would be the Django way of making sure these two model types wont have overlapping Ids?
class Customer(models.Model):
name = models.CharField(max_length=255)
class OnlineCustomer(models.Model):
name = models.CharField(max_length=255)
Edit 1:
Here is an example of something that I've done that works, but does not feel correct. Should I be inheriting from a concrete base class?
class UniqueID(models.Model):
pass
def create_unique_id():
try:
UniqueID = UniqueID.objects.create()
except:
# This try except is here to allow migration to pass since Customers need access to this function during migration
# This should never happen
return 0
return UniqueID.id
class Customer(models.Model):
id = models.IntegerField(primary_key=True, default=create_unique_id)
class OnlineCustomer(models.Model):
id = models.IntegerField(primary_key=True, default=create_unique_id)
As Vishal Singh commented, the UUIDField class from Django's Model can be used to create
A field for storing universally unique identifiers.
As mentioned here.
Usage could be as following:
import uuid
from django.db import models
class Customer(models.Model):
id_ = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255)
class OnlineCustomer(models.Model):
id_ = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255)
Related
Not super experienced with Django so I apologize if this is trivial. Say I had a category instance and I wanted to get access to all of the content objects that I have previously added to my foreign key. How would I do so?
class Organization(models.Model):
id = models.CharField(primary_key=True, max_length=200, default=uuid4, editable=False, unique=True)
name=models.CharField(max_length=200,unique=True)
phoneNumber=models.CharField(max_length=20)
logo=models.CharField(max_length=100000) # storing this as base 64 encoded
location=models.CharField(max_length=200)
class Category(models.Model):
categoryName=models.CharField(max_length=300, unique=True, primary_key=True)
associatedOrganizations=models.ForeignKey(Organization,on_delete=models.CASCADE,related_name='associatedOrgs',null=True,blank=True)
associatedContent=models.ForeignKey(Content, on_delete=models.CASCADE,related_name='associatedContent',null=True,blank=True)
associatedMeetingNotices=models.ForeignKey(MeetingNotice,on_delete=models.CASCADE,related_name='associatedMeetingNotices',null=True,blank=True)
For example:
say I had the following
healthcareCategory=models.Category.objects.get(pk="healthcare")
and I wanted to access all Organizations related to healthcare, what should I do?
This?
healthcareCategory.associatedOrganizations.all()
You are close. You may want to change that related name from associatedOrgs to be associatedorgs to follow more closely to the django coding style. Documentation on this has a few examples.
healthcare_category = Category.objects.get(pk="healthcare")
organizations = healthcare_category.associatedorgs.all()
The answer by #AMG is correct. If you had not defined a related_name for associatedOrganizations you could simply do
organizations = Organization.objects.filter(category__pk='healthcare')
But I think there is another issue. Am I correct in saying that an Organization can have only one Category, but a Category can have many Organizations?
If so, then I think the ForeignKey in your model is in the wrong place.
class Organization(models.Model):
id = models.CharField(primary_key=True, max_length=200, default=uuid4, editable=False, unique=True)
name=models.CharField(max_length=200,unique=True)
phoneNumber=models.CharField(max_length=20)
logo=models.CharField(max_length=100000) # storing this as base 64 encoded
location=models.CharField(max_length=200)
# The ForeignKey should be here:
category = ForeignKey(Category, on_delete=models.CASCADE)
class Category(models.Model):
categoryName=models.CharField(max_length=300, unique=True, primary_key=True)
# remove this
# associatedOrganizations=models.ForeignKey(Organization,on_delete=models.CASCADE,related_name='associatedOrgs',null=True,blank=True)
...
The ForeignKey is a ManyToOneField so you place it in the model that will be the many, and you link it to the model that will be the one.
Now you can find all organizations within the healthcare category like this:
organizations = Organization.objects.filter(category='healthcare')
I have just started with making a similar site to Pinterest and the site has follower/target system that I have barely any understanding of. So far, my models.py code is below:
from django.db import models
class User(models.Model):
username = models.CharField(max_length=45, null=True)
email = models.CharField(max_length=200, null=True)
password = models.CharField(max_length=200)
nickname = models.CharField(max_length=45, null=True)
target = models.ManyToManyField(self, through='Follow')
follower = models.ManyToManyField(self, through='Follow')
class Meta:
db_table = 'users'
class Follow(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='targets')
target = models.ForeignKey(User, on_delete=models.CASCADE, related_name='followers')
class Meta:
db_table = 'follows'
This code was made with reference to another StackOverflow thread
Django models: database design for user and follower
However, I am having trouble understanding how using "related_name='targets' in 'follower' and "related_name='followers'" in 'target' where I can't see any 'targets'(plural) or 'followers'(plural) in other areas of models.py
Should I get rid of that related_name, since there is no such table called "followers" or "targets"? And if you spot major errors in my code or logic, can you tell me? Thanks!
Should I get rid of that related_name, since there is no such table called followers or targets.
There is never a table named followers or targets. The related_name [Django-doc] is a conceptual relation Django makes to the other model (in this case User). It means that for a User object myuser, you can access the Follow objects that refer to that user through target for example with myuser.followers.all(), so:
Follow.objects.filter(target=myuser)
is equivalent to:
myuser.followers.all()
The default of a related_name is modelname_set, so here that would be follow_set. But if you remove both related_names, then that would result in a name conflict, since one can not add two relations follow_set to the User model (and each having a different semantical value).
if you spot major errors in my code or logic, can you tell me?
The problem is that since ManyToManyFields refer to 'self' (it should be 'self' as string literal), it is ambigous what the "source" and what the target will be, furthermore Django will assume that the relation is symmetrical [Django-doc], which is not the case. You should specify what the source and target foreign keys are, you can do that with the through_fields=… parameter [Django-doc]. It furthermore is better to simply define the related_name of the ManyToManyField in reverse, to avoid duplicated logic.
from django.db import models
class User(models.Model):
username = models.CharField(max_length=45, unique=True)
email = models.CharField(max_length=200)
password = models.CharField(max_length=200)
nickname = models.CharField(max_length=45)
follows = models.ManyToManyField(
'self',
through='Follow',
symmetrical=False,
related_name='followed_by',
through_fields=('follower', 'target')
)
class Meta:
db_table = 'users'
class Follow(models.Model):
follower = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='targets'
)
target = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='followers'
)
class Meta:
db_table = 'follows'
Here a User object myuser can thus access myuser.follows.all() to access all the users that they follow, myuser.followed_by.all() is the set of Users that follow myuser. myuser.targets.all() is the set of Follow objects that he is following, and myuser.followers.all() is the set of Follow objects that are following that user.
I have a model in which I need to represent different jobs for a labor application, for example:
from django.db import models
class PostFirstJobAd(models.Model):
fist_job_ad_title = models.CharField(max_length=225)
first_job_ad_description = models.TextField()
created_at = models.DateTimeField(auto_now=True)
class PostSecondJobAd(models.Model):
second_job_ad_title = models.CharField(max_length=225)
second_job_ad_description = models.TextField()
created_at = models.DateTimeField(auto_now=True)
class PostThirdJobAd(models.Model):
third_job_ad_title = models.CharField(max_length=225)
third_job_ad_description = models.TextField()
created_at = models.DateTimeField(auto_now=True)
Instantly you can see that I'm repeating title, description and created_at, I'm just changing field's name, it's not DRY and code is starting to smell. The reason for this is because I want to register every job separately inside django admin, so I will have clear situation inside site administration.
One way to make them DRY is to use Abstract base classes but I have a problem because from the docs:
This model will then not be used to create any database table.
Instead, when it is used as a base class for other models, its fields
will be added to those of the child class.
What will be the right approach in this case, can someone help me understand this.
Using abstract base models:
class JobAd(models.Model):
title = models.CharField(max_length=225)
description = models.TextField()
created_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class PostFirstJobAd(JobAd):
pass
class PostSecondJobAd(JobAd):
pass
class PostThirdJobAd(JobAd):
pass
This would create 3 tables. The base class JobAd does not have a table in the db.
Since you appear to have 3 different models with the exact same code, you should question whether you really need 3 different models at all. Another option is to just store them all in one table, and add another field for the "other" thing.
class JobAd(models.Model):
pos = models.CharField(max_length=100, choices=['first', 'second', 'third'])
title = models.CharField(max_length=225)
description = models.TextField()
created_at = models.DateTimeField(auto_now=True)
An integer field for pos is also possible.
First off, the abstract models might be what you need here. Depending on the business requirements, you may need to think a little harder on the architecture.
If, in fact, you do need to use abstract base classes:
class BaseJob(models.Model):
title = models.CharField(max_length=255)
# etc...
class Meta:
abstract = True
def method_1(self):
# base methods that work for instance data
Once that is defined, you can implement the base class in a concrete model. A concrete model is a model that doesn't use the abstract = True metaclass property (or proxy, etc.) like so:
class Job(BaseJob):
pass
If you need additional fields you can define them like any other model field but when you run makemigrations you'll find the fields get added in the migration generated.
In Django, I have the following models.py
class Product(RandomPrimaryIdModel):
feature1 = models.CharField(max_length=20, blank=True, null=True)
feature2 = models.CharField(max_length=20, blank=True, null=True)
feature3 = models.CharField(max_length=20, blank=True, null=True)
class Mattress(Product):
category_type = models.CharField(max_length=50)
size = models.CharField(max_length=5)
def category(self):
return "bedding"
category = property(category)
I have the following views.py file
def update(request, id):
product = Product.objects.get(id=id)
...
In this method, update, can I call a method defined in the "Mattress" model from the Product model. For example, I want to write: if product.type == "mattress" where type has been defined in the Mattress Model and Mattress is a sub-model of Product.
Your example seems to sit between two different ways you can go, but is currently not correct. What is happening is that you are creating two tables: Product, and Mattress, and they are completely unrelated. Regardless of the fact that Mattress subclasses Product, it is just inheriting its structure. You cannot query anything in the Product table about a mattress because a mattress is in the Mattress table.
One way to go is to consider a Product just abstract, to be subclassed by actual products:
class Product(RandomPrimaryIdModel):
class Meta:
abstract=True
This will prevent a Product table from being created. Then you would directly query a mattress via: Mattress.objects.filter()
But this seems a bit limiting in terms of introducing many types of products, and having to manage different tables for them. The other way to go is to use a Product table, but use generic relations to support attaching any type of other table as a content object:
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class Product(RandomPrimaryIdModel):
feature1 = models.CharField(max_length=20, blank=True, null=True)
feature2 = models.CharField(max_length=20, blank=True, null=True)
feature3 = models.CharField(max_length=20, blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
With this, you would be able to set the content_object to be a Mattress instance. You can then use the ContentType to query:
p_type = ContentType.objects.get(name="mattress")
Product.objects.filter(content_type=p_type)
This looks like a case of automatic down casting. I needed a similar approach for a shopping cart that held generic 'ProductBase' instances but I needed to access the children's specific functions which were the actual products of type ProductDownloadable, ProductShipped, etc.
Django does not natively support this, but one could code it through introspection or use django-model-utils and once that is installed you could do:
# return a list 'child' classes of Product - in your case Mattresses
mattress_list = Product.objects.all().select_subclasses()
# return the direct 'child' class of Product - in your case Mattress class
mattress = Product.get_subclass(id=some_id) # returns the 'child' subclass
mattress.foo() # executes method on foo on Mattress class (not on Product class)
I have the following models
class Group(models.Model):
name = models.CharField(max_length=32, unique=True)
class Subgroup(models.Model):
name = models.CharField(max_length=32, unique=True)
group = models.ForeignKey(Group)
class Keywords(models.Model):
name = models.CharField(max_length=32, unique=True)
subgroup = models.ForeignKey(Subgroup)
For each Subgroup I need to manage a list of keywords.
I'm trying to use django forms to automatically display a list (select box) where if I add or remove values to that list and then issue a form.save that it automatically updates the models and data.
How exactly can I do this? Are my models designed properly to allow this?
I think you can create form with MultipleChoiceField:
class MyForm(forms.Form):
to_select = forms.MultipleChoiceField(widget=forms.CheckboxInput, choices=[])
In this case you have to override form`s save method.
Did you try to create model form for subgroup class?
class MyForm(forms.ModelForm):
class Meta():
model=Subgroup