Django Model Reference to Multiple Foreign Key with Child Property - django

I have the following Models of customer details with each customers having different payment modes (eg. cash, online transfer, etc...) :
class Customer(models.Model):
#some customer details
class Payment(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.RESTRICT, related_name='payments')
payment_mode = models.CharField(max_length=255, blank=True, null=True)
And I would like to add a new Invoice Model to include the customer as well as the customer's payment modes.
class Invoice (models.Model):
customer = models.ForeignKey(Customer, on_delete=models.RESTRICT, related_name='payments')
payment_mode = models.ForeignKey(Customer.payments.payment_mode, on_delete=models.RESTRICT)
I am going to create an Invoice for a customer and will input the customer's available payment mode. But the the invoice's payment mode is giving me an AttributeError: 'ReverseManyToOneDescriptor' object has no attribute 'payment_mode'.
May I know how do I set up the reference to the customer's child data?
Thank you.

What you have is not a valid field definition.
You can reference Payment directly
payment_mode = models.ForeignKey(Payment, on_delete=models.RESTRICT)

Why is the Invoice model even required? You have the same fields already in the existing models.
You can simply make a view to do this.
For example,
def show_invoice(request, pk):
# this pk value should be sent by your frontend and represents your Primary Key value for the current customer
customer = Customer.objects.get(pk=pk)
return render(request, 'some_html_page.html', {'customer': customer})
Now in your some_html_page.html, you can show the details you want using the 'context' to the render function ({'customer': customer}) we just passed.
Models in Django should be thought of as Tables in SQL; you are not supposed to make a new one every time you want to "infer" something, rather you should make them when you want to 'store' something (or normalize existing tables/models). The Invoice model does not do either of these two things.
You can give this a read to understand how to write views in Django this.
In the case where you really want to make an Invoice model you don't need to make a payment_mode field, since you're already pointing to the Customer model which is, in turn, pointing to the Payment model.

Related

How to make a model parameter unique by a other parameter in Django?

I want my id field to be unique per each customer field. Just like the option unique_for_date from Django (https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique) but in this case, not date but customer.
class Sample(NGObject):
id = models.CharField(max_length=128, null=True, blank=False)
customer = models.ForeignKey(Customer, related_name="blood_samples", on_delete=models.SET(get_default_customer))
I believe this should be done, before the save() method?
When a User writes the wrong ID (that already exists) I would also like to present the information in the Admin Form just like it would for normal unique error.
class Meta:
unique_together = ('sample_id', 'customer',)
This has done the trick :)

Django Query ManyToMany with Custom Through Table Field Data

I've been trying to figure this one out for a while now but am confused. Every ManyToMany relationship always goes through a third table which isn't that difficult to understand. But in the event that the third table is a custom through table with additional fields how do you grab the custom field for each row?
Here's a sample table I made. How can I get all the movies a User has watched along with the additional watched field and finished field? This example assumes the user is only allowed to see the movie once whether they finish it or not so there will only be 1 record for each movie they saw.
class Movie(models.Model):
title = models.CharField(max_length=191)
class User(models.Model):
username = models.CharField(max_length=191)
watched = models.ManyToMany(Movie, through='watch')
class Watch(models.Model):
user = models.Foreignkey(User, on_delete=models.CASCADE)
movie = models.Foreignkey(Movie, on_delete=models.CASCADE)
watched = models.DateTimeField()
finished = models.BooleanField()
Penny for your thoughts my friends.
You can uses:
from django.db.models import F
my_user.watched.annotate(
watched=F('watch__watched'),
finished=F('watch__finished')
)
This will return a QuerySet of Movies that contain as extra attributes .watched and .finished.
That being said, it might be cleaner to just access the watch_set, and thus iterate over the Watch objects and access the .movie object for details about the movie. You can use .select_related(..) [Django-doc] to fetch the information about the Movies in the same database query:
for watch in my_user.watch_set.select_related('movie'):
print(f'{watch.movie.title}: {watch.watched}, {watch.finished}')

REST Framework: Update field in one model and track changes in another model

I have two models:
class CustomUser(models.Model):
...
act = models.CharField(max_length=10)
class ActHistory(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
last_act = models.CharField(max_length=10)
act_time = models.DateTimeField(auto_now_add=True)
I would like to create a single API endpoint /update/ with DRF that does this:
If value vs existing act value in the model is the same, do nothing.
If the values are different, update the CustomUser for the authenticated user with the value
Then insert a record row in ActHistory with user=authenticated user, last_act =
All the docs I managed to find only support doing either the update or create actions with each API point.
Thanks in advance!

Django: sub-fields within a model field

In my primary class model Deals, I have certain fields as description, price, date_created etc. I now have to add some fields having sub-fields to it. For eg, I'm trying to add an age field to Deals. This age field further has subfields (like score_for_kid, score_for_baby, score_for_old etc), and I want to edit these scores from the admin.
Here is my models.py:
class Deals(models.Model):
description = models.TextField()
price = models.DecimalField(max_digits=7, decimal_places=2)
url = models.URLField(verify_exists=False)
currency = models.CharField(max_length=3)
created_date = models.DateField(auto_now_add=True)
kid_score = models.IntegerField(max_length=2,default=0)
teenager_score = models.IntegerField(max_length=2,default=0)
youth_score = models.IntegerField(max_length=2,default=0)
old_score = models.IntegerField(max_length=2,default=0)
I don't want to store all these sub fields (around 20-25 in 4 different fields) in the model, instead an age field connected to these subfields. Would a ManyToManyField work for this?
The underlying requirement is that when a user selects a subfield (say kids) on the browser, all the objects having higher kid scores are displayed.
I'm very new to Django and any help on this would be great. Thanks.
If I understand your question properly ou need to use ForeignKey fields.
class Deals(models.Model):
description = models.TextField()
price = models.DecimalField(max_digits=7, decimal_places=2)
#...
age = models.ForeignKey(Age)
class Age(models.Model):
kid_score = models.IntegerField(max_length=2,default=0)
teenager_score = models.IntegerField(max_length=2,default=0)
#...
Have a good read of the docs on Models. You might also find it useful to do some reading on relational databases / basic sql.
When you come to edit your objects in the django admin, you'll probably want to use an InlineModelAdmin class.
UPDATE
re-reading your question, it sounds like you might simply want to show / hide these additional fields on the main Deal model. If this is the case then you want to use fieldsets in the admin, with a class 'collapse'. There's an example in the docs.
If you want each Deal record to have multiple kid_score's associated with it then you want a foreign key. If each Deal can only have one kid_score then you need to keep the kid_score (and other) fields in the main model (if this is confusing then definitely do some reading on sql / relational databases).

Designing without duplicate foreignkey references in Django

I want to create an expense tracking application, where each user can enter expenses and classify them into his own categories. Here is the model definition that I use:
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
user = models.ForeignKey(User, related_name="my_categories")
name = models.CharField(max_length=50)
class Expense(models.Model):
date = models.DateField()
amount = models.IntegerField()
description = models.TextField()
category = models.ForeignKey(Category)
user = models.ForeignKey(User)
Each category will have to be associated with a user so that we can display each user his own categories to choose while entering the expense. For similar reasons, each expense record should be associated with a user. But in definition of Expense, we are having 2 references to the User models, one directly through 'user' field and another through the 'category' field which has a user reference.
I believe that multiple references like this is a bad thing. Is there a better way to model this? I understand that we can find out the user from the category reference, but it seems a roundabout way of doing it.
Although your db is not 100% normalized, in your case, I do not believe the second reference is redundant. Both 'an expense' and 'a category' are well defined entities, which belong to a user. If you will later want to change your foreign key to allow a null category or to a ManyToManyField, you will notice immediatly that both user fields are required. Lookups by user are also much easier for the db and developer when the column is there.