class Patient(models.Model):
user = models.OneToOneField(User, related_name='patient', on_delete=models.CASCADE)
id_type = models.CharField(max_length=300)
id_number = models.CharField(max_length=300)
creation_date = models.DateField(default=datetime.date.today)
class Allergie(models.Model):
name = models.CharField(max_length=300, default="X")
class PatientAllergies(models.Model):
patient = models.ForeignKey(Patient, related_name="patient_allergies", on_delete=models.CASCADE)
allergie = models.ForeignKey(Allergie, on_delete=models.CASCADE, null=True)
professional_contract = models.ForeignKey(ProfessionalContract, null=True ,on_delete=models.CASCADE)
Is it possible to retrieve a patient objecto with a property that is a list of all his allergies, including name and id with these models?
you have the PatientAllergies as a chain,
so
patientAllergies = PatientAllergies.objects.get(patient.id_number='0000')
patientAllergies.allergie #you get the single allergie model connect with it, take care it is a foreignKey so it is singolar and not many
patientAlleriges.patient.user #will give you access to all the data of the user
You can achieve this with prefetch_related and Prefetch like so:
Patient.objects.prefetch_related(
Prefetch('patient_allergies__allergie', to_attr='allergies')
)
EDIT: Just learned that to_attr will not work on multiple levels of prefetch. Another approach I can think of is use a model property for Patient that returns its related allergies like this:
class Patient(models.Model):
#property
def allergies(self):
return Allergie.objects.filter(patientallergies_set__patient=self)
Then in your serializer, the allergies field can use the Allergies serializer
Related
I have 3 models
class Person(models.Model):
name = models.CharField(max_length=128)
class Company(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField (Person, through = 'Membership', related_name = 'companies')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
is_admin = models.BooleanField()
I can then call person.companies.all() to get the list of companies associated with person.
How do I create a manager to have the list of companies associated with person, but whose person is admin (is_admin = True)?
You can create a manager like the following:
managers.py:
from django.db import models
class AdminCompaniesManager(models.Manager):
def get_queryset(self):
return super().get_queryset().companies.filter(membership__is_admin=True)
and then in your Person model (please remind the objects manager):
class Person(models.Model):
name = models.CharField(max_length=128)
objects = models.Manager()
administered_companies = AdminCompaniesManager()
Now you can easily call the following (e.g. in your views):
my_person.administered_companies.all()
PS: a very efficient option (e.g. if you are in a view and you need the list of company ids by a given person) is to query the membership model directly, so you can optimize the query for data retrieval from DB avoiding the joins:
Membership.objects.filter(is_admin=True, person=person).values_list('company_id')
You can filter with:
person.companies.filter(membership__is_admin=True)
This will filter the junction table Membership, such that it will only retrieve Companys for which the Membership has is_admin set to True.
Another option is to retrieve this with:
Company.objects.filter(membership__is_admin=True, members=person)
You can attach this to the Person model with:
class Person(models.Model):
name = models.CharField(max_length=128)
#property
def admin_companies(self):
return self.companies.filter(membership__is_admin=True)
Is there a way to refer to specific object of Model? Suppose I have some models like below:
# models.py
class VehicleCategoryCode(models.Model):
category = models.CharField(max_length=5)
name = models.CharField(max_length=20)
class Code(models.Model):
category = models.ForeignKey(VehicleCategoryCode, on_delete=models.CASCADE)
index = models.CharField(max_length=4, blank=True)
label = models.CharField(max_length=50)
order = models.CharField(max_length=20, blank=True)
is_active = models.BooleanField(default=True)
# pay attention to the Model
class Vehicle(models.Model):
label = models.CharField(max_length=80)
model = models.CharField(max_length=30)
Currently Vehicle is not linked to any model.
Now Code model is ForeignKey to VehicleCategoryCode, which has two objects. In the VehicleCategoryCode the first object label (for convenience sake) will be referenced by Vehicle.label, and the second object model (once again for convenience) will be referenced by Vehicle.model. So each field in Vehicle can refer to the same model, but different objects.
So basically I'm wondering if something like the pseudo code below can be achieved anyhow.
class Vehicle(models.Model):
label = models.ForeignKey(VehicleCategoryCode__name='label', on_delete=models.CASCADE)
model = models.ForeignKey(VehicleCategoryCOde__name='model', on_delete=models.CASCADE)
Any suggestion or advice would be appreciated. Thank you.
You can make use of the limit_choices_to=… parameter [Django-doc]:
Vehicle(models.Model):
label = models.ForeignKey(
Code,
limit_choices_to={'category__name': 'label'},
on_delete=models.CASCADE
)
model = models.ForeignKey(
Code,
limit_choices_to={'category__name': 'model'},
on_delete=models.CASCADE
)
For ModelForms and in the ModelAdmin it will limit the choices, note however that tese are not enforced by the database.
It's my first time creating a Django website with models, and in my first attempt to insert data into my table I'm getting this error.
My models are as follows:
class User(AbstractUser):
pass
#https://docs.djangoproject.com/en/3.1/topics/auth/default/
class Listing(models.Model):
listingID = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="listID")
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myListing", null=True)
watchers = models.ManyToManyField(User, blank=True, related_name="watchlist")
title = models.CharField(max_length=30)
description = models.TextField()
creation_date = models.DateField(auto_now=True)
img_url = models.URLField()
active = models.BooleanField(default=True)
def __str__(self):
return f"{self.title}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.SET_NULL, related_name="bidsMadeOnMe", null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myBids", null=True)
price = models.FloatField()
creation_date = models.DateField(auto_now=True, null=True)
def __str__(self):
return f"Bid={self.price}"
and the view that handles the form submission is this one:
#login_required
def create_listing(request):
if request.method == "POST":
user = User.objects.get(username=request.user.username)
l = Listing(created_by=user,
title=request.POST["title"],
description=request.POST["desc"],
# https://stackoverflow.com/questions/12176585/handling-dates-over-request-get
creation_date=models.DateTimeField(auto_now_add=True),
img_url=request.POST["image_url"]
)
l.save()
b = Bid(l,
user,
request.POST["initial_bid"],
models.DateTimeField(auto_now_add=True)
)
b.save()
return render(request, "auctions/index.html")
I know the problem is the way I'm adding the data but I can't fix it. Can someone give me some light?
Your problem (well, several actually) is this:
b = Bid(l, user, request.POST["initial_bid"], models.DateTimeField(auto_now_add=True))
You're constructing a model instance by positional arguments instead of keyword arguments. This can be done, but then the invisible "id" column that has been added to the Bid model, is the first argument.
In Django we never construct models like that, but always use keyword arguments, so we're not depending on field order:
b = Bid(listing=l, user=user, ...))
Once you're solved that, your next problem is the date field.
Don't assign fields to model instances. Fields are class declarations, they don't belong on instances. Fields describe on a class (= a Model), what kind data to expect. On the instance, you assign that data.
In this case, your definition for the field is wrong on the model and on the instance you shouldn't even assign it - it will be automatically filled.
Overall, it feels like you haven't gone through Django's tutorial or did not fully understand the concepts. I suggest you go through it.
Hello guys I have one query in my Django project.
First of all, You can see that I have two Django models named BookSeller and Book
Bookseller model
class BookSeller(models.Model):
user_name = models.CharField(max_length=200)
user_email = models.CharField(max_length=200)
user_password = models.CharField(max_length=200)
user_phone = models.CharField(max_length=100)
user_photo = models.ImageField(upload_to='book/seller_photos/%Y/%m/%d/', blank=True)
user_address = models.CharField(max_length=300)
user_state = models.CharField(max_length=100)
user_city = models.CharField(max_length=100)
def __str__(self):
return self.user_name
Book Model
class Book(models.Model):
book_owner = models.ForeignKey(BookSeller, related_name='book_seller', on_delete=models.CASCADE)
book_category = models.CharField(max_length=200)
book_title = models.CharField(max_length=200)
book_price = models.IntegerField()
book_edition = models.CharField(max_length=200)
book_author = models.CharField(max_length=200)
book_old = models.IntegerField()
book_page = models.IntegerField()
book_description = models.TextField(max_length=200)
book_image_1 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_2 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_3 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_4 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
def __str__(self):
return self.book_title
Want to DO: In my project I want to find books by that book seller's city.
For example, if I write city name 'Silicon Valley' in my search field then it should show me all "Books" that's Sellers(BookSeller) belonging to Silicon Valley.
Query: So my query is how can I do that Django Query set, because I can't find out any query which can do this task.
If you guys have any other solution then please suggest me!!!
For finding the books by some book seller's city you can simly filter the Book instances like so:
Book.objects.filter(book_owner__user_city="Silicon Valley")
One other problem I noticed is that I think you misunderstand related_name attribute in ForeignKey.
The related_name attribute specifies the name of the reverse relation from the BookSeller model back to Book model.
If you don't specify a related_name, Django automatically creates one using the name of your model with the suffix _set.
For instance more appropriate related name in your FK would be books, and without defining it would default to book_set.
book_owner = models.ForeignKey(BookSeller, related_name='books', on_delete=models.CASCADE)
Here is an example, lets assume you have 1 instance of BookSeller and 2 isntances of Book with FK to that instance of BookSeller.
my_book_seller = BookSeller(...)
my_book_1 = Book(book_owner=my_book_seller, ...)
my_book_2 = Book(book_owner=my_book_seller, ...)
Now in your case doing the my_book_seller.book_seller.all() (since you defined the related_name to be book_seller) would return you the two Book instances belonging to my_book_seller. This doesn't make much sense.
On the other hand having the related_name='books' you would get the same books by doing my_book_seller.books.all().
You can find more info in docs.
You can do that like this
Book.objects.filter(book_owner__user_city="Silicon Valley")
and you learn more about various kinds of joining at
this link
You can get the desired results doing something like
books_by_seller_city = Book.objects.filter(book_owner__user_city='Silicon Valley')
Note the use of __ which tells the ORM to look at the referenced model attribute.
You can do with q look ups also, in that case you can add more fields in your query.
queryset = Book.objects.filter(Q(book_owner__user_city__icontains=query)|
.................)
I would like to ask some advice on Modeling a specific model behavior.
Basically I have a model Item. It describes the name and description of an item.
I have a inventory, which should hold a "List" of items, considering the quantity of each item should be specified in the inventory.
Each User should have one unique inventory.
Here's what I'm trying to do:
class User(models.Model):
name = models.CharField(max_length=100)
invetory =models.ForeignKey(inventory,on_delete=models.CASCADE)
class item(models.Model):
name =models.CharField(max_length=40)
description = models.TextField(max_length=200)
value = models.FloatField()
class inventory(models.Model):
?
I'm not sure if this is the right approach.
You should use many-to-many relations. First of all you should delete the FK from the User model. Then create a separate model for items and finally link many users to many items (one user can handle multiple items and one item can belong to multiple users). Something like that:
class User(models.Model):
name = models.CharField(max_length=100)
class item(models.Model):
name =models.CharField(max_length=40)
class inventory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
item = models.ForeignKey(item, on_delete=models.DO_NOTHING)
quantity = models.FloatField()
PS Class names should use PascalCase convention https://www.python.org/dev/peps/pep-0008/?#class-names
class User(models.Model):
name = models.CharField(max_length=100)
class Inventory(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
class Item(models.Model):
name =models.CharField(max_length=40)
description = models.TextField(max_length=200)
value = models.FloatField()
invetory =models.ForeignKey(Inventory,on_delete=models.CASCADE)
This should work as per your specification. We have tied up inventory to a user and each item will have a foreign key to Inventory table.
Now you can do
1. To access inventory you can do `user.inventory`
2. To get a list of items `user.inventory.item_set`
3. You should use the `post_save` signal to create the inventory object.
class inventory(models.Model):
user = models.ForeignKey(User, default=User.objects.first())
item = models.ForeignKey(Item, default=Item.objects.first())
count = models.IntegerField(default=0)
I think this would make a better design.