Django models dependencies and transfer ownership - django

What I am trying to build is a app that can deal with honey production management.
There are number of producers that produce honey pots and they can give their pots to a variety of stores that have their customers. One producer can give his production to many stores, and a store can have honey pots from many producers. Honey pots can be tracked by pot_id. The models.py looks like this:
class Produser(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
class Store(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
produser= models.ManyToManyField(Produser)
class Customer(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
store = = models.ForeignKey(Store, on_delete=models.CASCADE)
class HoneyPot(models.Model):
produced_date = models.DateField(auto_now=False)
pot_id = models.CharField(max_length=25, blank=False)
produser= models.ForeignKey(Produser, on_delete=models.CASCADE)
store= models.ForeignKey(Store, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
I'm struggling to find how to modify the models in the way that one pot to be owned or by producer or a shop or a customer. As right now when a new pot is created store and customers are required fields.

You can say that Produser, Store and Customer all have something in common, i.e. they can own a HoneyPot. Meaning they are specializations of let's say an entity that can own a HoneyPot. To model this we would simply add an extra model which Produser, Store and Customer all will either inherit from or have a one to one relationship with.
Using a OneToOneField [Django docs]:
We can simply make the relationship by using a OneToOneField:
class HoneyPotOwner(models.Model):
PRODUCER = 'P'
STORE = 'S'
CONSUMER = 'C'
TYPE_CHOICES = [
(PRODUCER, 'Producer'),
(STORE, 'Store'),
(CONSUMER, 'Consumer'),
]
owner_type = models.CharField(max_length=1, choices=TYPE_CHOICES)
class Produser(models.Model):
honey_pot_owner = models.OneToOneField(HoneyPotOwner, on_delete=models.CASCADE)
...
class Store(models.Model):
honey_pot_owner = models.OneToOneField(HoneyPotOwner, on_delete=models.CASCADE)
...
class Customer(models.Model):
honey_pot_owner = models.OneToOneField(HoneyPotOwner, on_delete=models.CASCADE)
...
class HoneyPot(models.Model):
produced_date = models.DateField(auto_now=False)
pot_id = models.CharField(max_length=25, blank=False)
owner = models.ForeignKey(HoneyPotOwner, on_delete=models.CASCADE)
Using Multi-table inheritance:
We can have Produser, Store and Customer inherit from HoneyPotOwner this is called Multi-table inheritance. This implicitly makes the OneToOneField, but has a few advantage that accessing the related fields becomes a little easier:
class HoneyPotOwner(models.Model):
PRODUCER = 'P'
STORE = 'S'
CONSUMER = 'C'
TYPE_CHOICES = [
(PRODUCER, 'Producer'),
(STORE, 'Store'),
(CONSUMER, 'Consumer'),
]
owner_type = models.CharField(max_length=1, choices=TYPE_CHOICES)
class Produser(HoneyPotOwner):
...
class Store(HoneyPotOwner):
...
class Customer(HoneyPotOwner):
...
class HoneyPot(models.Model):
produced_date = models.DateField(auto_now=False)
pot_id = models.CharField(max_length=25, blank=False)
owner = models.ForeignKey(HoneyPotOwner, on_delete=models.CASCADE)

Related

How to create one to many generic relation between objects in Django

I have these two models:
How do I correctly set the relationship so I can do backward queries?
class Client(models.Model):
city = models.CharField(max_length=16)
worker = models.ForeignKey(
"Worker",
null=True,
default="1",
on_delete=models.SET_DEFAULT,
related_name="assigned_workers",
)
class Meta:
abstract = True
And:
class Worker(models.Model):
first_name = models.CharField(max_length=16)
last_name = models.CharField(max_length=16)
gender = models.CharField(max_length=1)
What I want to do is set up the models in a way I can do the following queries:
Query the clients assigned to a worker using the worker object. Something like this:
Worker.objects.assigned_workers.all()

How to change field value dynamically depended on dropdown selection in django

I've been searching Google, but couldn't find a simple answer to this problem:
I have a django models that stores students information and three other models like this:
class Level(models.Model):
name = models.CharField(max_length=50)
class Pricing(models.Model):
level = models.ForeignKey(Level, on_delete=models.PROTECT)
price = models.PositiveSmallIntegerField(default=0)
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
price = models.PositiveSmallIntegerField(default=0)
I want the Enrollment.price field to be populated dynamically depending on Enrollment.level field value. In javascript, it amounts to setting an event listener to Enrollement.level, but I can't find the equivalent in django.
hi you can modify your save method to fill automatically field price from Level model
Enrollment.level
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
price = models.PositiveSmallIntegerField()
def save(self,*args,**kwargs):
self.price = Pricing.objects.get(level=self.level).price
super().save(*args,*kwargs)
but I recommend to rewrite your model like above example because its simple and you can access to price of every level directly
like Enrollment.level.price
class Level(models.Model):
level = models.CharField(max_length=50,unique=True)
price = models.PositiveSmallIntegerField(default=0)
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
I hope it helped you

how to give custom validation in django and djangorestframework on creating an API?

Here is my question I am creating address model, in that city, district I am accepting null values, Because for some API View I will accept Null values, but another API I will call this same models that time I want to validate that field is required, How Its is possible Here is my below code example.
models.py
class Address(models.Model):
address_line1 = models.CharField(max_length=250)
address_line2 = models.CharField(max_length=250, blank=True, null=True)
city = models.ForeignKey('Cities', on_delete=models.DO_NOTHING, blank=True, null=True)
district = models.ForeignKey('Districts', on_delete=models.DO_NOTHING, blank=True, null=True)
class Assignaddress(models.Model):
address = models.ForeignKey(Address, on_delete=models.CASCADE)
owner_name = models.CharField(max_length=255)
class dont`Assignaddress(models.Model):
address = models.ForeignKey(Address, on_delete=models.CASCADE)
owner_name = models.CharField(max_length=255)
Now in serializer.py
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = ('address_line1','address_line2','city','district')
class AssignaddressSerializer(serializers.ModelSerializer):
class Meta:
model = Assignaddress
fields = ('address ','owner_name ')
class dont`AssignaddressSerializer(serializers.ModelSerializer):
class Meta:
model = dont`Assignaddress
fields = ('address ','owner_name ')
now How can I validate Assignaddress you have to pass city and district is required and don`tAssignaddress its not neccessary
Sorry for not writting views.py
So in one of your serializers you want to accept null values? You can do this with allow_null and / or required (for fields that should not be supplied during deserialization). Be sure to check out the corresponding Django Rest Framework documentation.
Example (out of my memory - check Django Rest Framework documentation for specific use case):
class AssignaddressSerializer(serializers.ModelSerializer):
address = serializers.PrimaryKeyRelatedField(many=False, allow_null=True)
class Meta:
model = Assignaddress
fields = ('address ','owner_name ')

Having trouble linking two fields with one another, then implementing them to another model

I'm working on a project which helps users find jobs.
So one of the models, named Oferta is used for details about a job. Someone who is looking for emplooyes, just completes a form which is based on this model, and people will be looking at it.
Here's this model:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
cor = models.CharField(max_length=50)
dataSolicitare = models.DateField(default=date.today)
denumireMeserie = models.CharField(max_length=50)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
The COR field is the code asociated to a job. Also, denumireMeserie means job name.
So these should be linked. Let's say, if code 1 means "Cook", these should be link - there will be no other job with a different code, or another job for code 1.
So, in my opinion, these two fields should have a OneToOne relationship between them, if I'm not mistaken.
But these codes and jobs need to be implemented in the database - so they need a model too.
class CORMeserii(models.Model):
CodCOR = models.CharField(max_length=25, primary_key=True, unique=True)
MeserieCor = models.OneToOneField(CodCOR, max_length=50, unique=True, on_delete=models.CASCADE)
And here is how I tried to do it, but obviously it won't work, because onetoonefield needs a model as the first parameter.
So, my questions are:
How can I link these two fields as I told you, and then link Oferta.cor to CORMeserii.CodCOR and Oferta.denumireMeserie to CORMeserii.MeserieCor?
(because each job with its code and name should be implemented in the database, then chosen in each Oferta (which means offer))
As Dirk pointed out on your previous question, you have not understood what relationship fields do in Django.
A ForeignKey or a OneToOneField gives you access to the entire related object. This means you can access any of the fields on that related object.
So your Oferta model does not need a denumireMeserie field; that belongs on the other model, which we might call "Job". Oferta has a link to that model, ie a ForeignKey:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey('Job', on_delete=models.CASCADE)
and Job has the details of the job:
class Job(models.Model):
cor = models.CharField(max_length=50)
denumireMeserie = models.CharField(max_length=50)
Now you can create a Job and an Oferta for that job:
my_job = Job.objects.create(cor=1, denumireMeserie='Cook')
my_oferta = Job.objects.create(job=my_job, ...rest of the fields...)
Now you can access the job name via the relationship:
print(my_oferta.job.denumireMeserie)
which will give you "Cook".

How to use two unique constraints in Django model?

I have a Django model for a player of a game
class Player(models.Model):
name = models.CharField(max_length=50)
team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
game = models.ForeignKey('Game', on_delete=models.CASCADE)
objects = GameManager()
class Meta:
unique_together = ('name', 'game',)
I have only one unique constraint, that the name and the game are unique together.
Now, I would like to extend our page by adding registered users. So, I would add this to the model.
user = models.ForeignKey('auth.User', on_delete=models.CASCADE, blank=True, null=True)
So, an registered user can subscribe to a game by adding a name, team, game, and his/her user. However, the user should only be able to add his account once to an game, which would be a second unique constrain
unique_together = ('user', 'game',)
Is it possible to give in Django two unique constraints to the model? Or do I have to search in the table manually prior to saving the new entries? Or is there a better way?
Yes, in fact by default unique_together is a collection of collections of fields that are unique together, so something like:
class Player(models.Model):
name = models.CharField(max_length=50)
team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
game = models.ForeignKey('Game', on_delete=models.CASCADE)
objects = GameManager()
class Meta:
unique_together = (('name', 'game',), ('user', 'game',))
Here we thus specify that every name, game pair is unique, and every user, game pair is unique. So it is impossible to create two Player objects for the same user and game, or for the same game and name.
It is only because a single unique_together constraint is quite common, that one can also pass a single collection of field names that should be unique together, as is written in the documentation on Options.unique_together [Django-doc]:
Sets of field names that, taken together, must be unique:
unique_together = (("driver", "restaurant"),)
This is a tuple of tuples that must be unique when considered
together. It's used in the Django admin and is enforced at the
database level (i.e., the appropriate UNIQUE statements are included
in the CREATE TABLE statement).
For convenience, unique_together can be a single tuple when dealing with a single set of fields:
unique_together = ("driver", "restaurant")
You should use models.UniqueConstraint (reference).
As noted in the reference:
UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.
Do this:
class Meta:
constraints = [
models.UniqueConstraint(fields=['name', 'game'], name="unique_name_game"),
models.UniqueConstraint(fields=['user', 'game'], name="unique_user_game"),
]
For example please refer to this :-
class Stores(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=50)
lat = models.FloatField()
lng = models.FloatField()
merchant = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name="stores")
def __str__(self):
return "{}: {}".format(self.name, self.address)
class Meta:
verbose_name_plural = 'Stores'
class Items(models.Model):
name = models.CharField(max_length=50, unique=False)
price = models.IntegerField()
description = models.TextField()
stores = models.ForeignKey(Stores, on_delete=models.CASCADE, related_name="items")
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Items"
unique_together = ('name', 'stores',)