hidden form to save aggregated values to model - python

I am creating a small django invoicing system for my first python project and I am stuck on this rather large issue handling data. I have a hierarchy of models that I use to easily input the data from paper. I have "services", which are migrated to "invoice", which are then migrated to "Bill Period" that the user will view all of their services provided for that month. The code will explain it better. What I need is a final model with an "Agency To Bill" and "Total" fields with a "Paid" booleanfield so I can keep track of payments and use these value with django-authorizenet. Using models is still new for me, so I'm stumped on how to do this. I am thinking that when the user views the invoice-detail page, a hidden form will be submitted with the cost values added together.
# models.py tiers
# compiled invoice with sum of all "cost" in
# bill period would be the last step
class Service(models.Model):
name_of_service = models.CharField(max_length="50")
cost = models.CharField(max_length="50")
def __unicode__(self):
return unicode(self.name_of_service)
class Bill_Period(models.Model):
start_date = models.DateTimeField(blank=True, null=True)
end_date = models.DateTimeField(blank=True, null=True)
def __unicode__(self):
return unicode(self.start_date)
class invoice(models.Model):
date_of_service = models.DateTimeField(default=timezone.now(),blank=True)
agency_to_bill = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True)
patient = models.ForeignKey('users.Patient', blank=True)
therapy_completed = models.ForeignKey('Service', blank=True)
def __unicode__(self):
return unicode(self.agency_to_bill)
class compiled_invoice(models.Model):
# month, total, paid
# views.py i use to handle the information
# error message "Relation fields do not support nested lookups"
def InvoiceDetail(request, month, year):
current_user = request.user
invoice_detail = invoice.objects.filter(date_of_service__year=year,
date_of_service__month=month,
agency_to_bill=current_user)
c = invoice.objects.filter(paid=False,
date_of_service__year=year,
date_of_service__month=month,
agency_to_bill=current_user)
total = invoice.objects.filter(therapy_completed__Service__cost__isnull=True).aggregate(Sum('cost'))
return render_to_response('invoice-detail.html', {'invoice_detail': invoice_detail,
'current_user': current_user,
'month': month,
})
Any help/advice would be appreciated, because at this point I'm stuck. This hidden form is my last ditch effort.

Related

Django displaying default photo next to each category

Im new to Django and don't really know how to write the part of code. I have few categories under Class Offers, I would like to add default photo for each category, so while adding a new offer the default photo will be connected to the category
my Model of offer:
CATEGORY = (
("Babysitting", "Babysitting"),
("Housework", "Housework"),
("Private lessons", "Private lessons"),
("Agro", "Agro"),
)
class Offers(models.Model):
category = models.CharField(choices=CATEGORY, max_length=20, null=True)
description = models.CharField(max_length=255)
paid_per_hr = models.IntegerField()
created = models.DateTimeField(auto_now_add=True )
updated = models.DateTimeField(auto_now_add=True)
i'm bit stuck with problem on how to assign the default photo different to each category
class AddOfferView(LoginRequiredMixin, View):
def get(self, request):
form = OfferForm()
return render(request, 'offer.html', {'form': form})
I can add the new offer with default one phono but then each category has same photo.

filter user records based on their names

I simply have a django medical website where users have their medical records and can view when logged in.
I have achieved the filtering based on user that is logged in, what i want is another user(doctor) to see this records based on user(patient he selects). currently the doctor can see if the record is one(using get_object_or_404, but i want loop over many records.
The models.py
class Medrecs(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE, related_name="meds")
title = models.CharField(max_length=60, null=True)
doctor = models.ForeignKey('Doctors.Doctor', null=True, on_delete=models.PROTECT)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now=True, null=True)
meds = models.TextField()
def __str__(self):
return self.title
Views.py
def detail(request, pat_id):
patient = get_object_or_404(Patient, pk=pat_id)
medrecs = Medrecs.objects.all().filter(user=request.user)
return render(request, 'MyDoc/detail_pat.html', {'patient': patient}, {'medrecs': medrecs})
In the view above i can see the patient records which are single records, but the medrecs(Medical records am unable to filter them based on the user(patient), it just gives me the page with the code(the template page unexecuted ). Medrecs.objects.filter(user=request.user) same case, .get will bring the number of rows and an error multipleobjects returned.
As a side note i was able to filter this records in the user's(profile page) with the view:
def my_profile(request):
if request.user.is_authenticated:
meds = Medrecs.objects.all().filter(user=request.user)
return render(request, 'MyDoc/my_profile.html', {'meds': meds})
else:
return redirect('MyDoc:login_patient')
Asking for help please.And thanks
If I understood correctly, the problem may be that you are using the wrong field to filter. Why do you have the user as a foreign key?. If you are saving Medrecs to a doctor and a patient maybe you should filter this way.
#you are filtering the medrecs by the user field
medrecs = Medrecs.objects.all().filter(user=request.user)
#Instead try this (if the doctor is logged in)
doctor = """your_get_doctor_method"""
medrecs = Medrecs.objects.all().filter(doctor=doctor,patient__id=pat_id)

Django 3 - Making Model's FK Dropdown Display Current User's Data Only

I'm creating my first app with Django and still have a lot to learn, but right now I am completely stuck and need some help. I have a model for Customers and Tickets. I have it so different users can save new customers/tickets and only view their data from the dashboard once logged in. However, when creating a new ticket, there is a dropdown option to select customer for the ticket - and the current user is able to see every users customers.
Here is the code, I'll share more code if needed, but I think this covers what I have going on...
forms.py
class TicketForm(ModelForm):
class Meta:
model = Ticket
fields = ['number', 'customer','date_created','work_description','mechanics','status']
views.py
def createTickets(request):
form = TicketForm()
if request.method == 'POST':
form = TicketForm(request.POST)
if form.is_valid():
newticket = form.save(commit=False)
newticket.shopowner = request.user
newticket.save()
return redirect('tickets')
context = {
'form': form
}
return render(request, 'createticket.html', context)
models.py
class Ticket(models.Model):
def default_number():
no = Ticket.objects.count()
return no + 1
shopowner = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
number = models.CharField(max_length=30, unique=True, default= default_number)
customer = models.ForeignKey(Customer, default=1, on_delete= models.SET_DEFAULT, blank=True)
date_created = models.DateField(default=timezone.now)
work_description = models.TextField(verbose_name="Service Details: ")
mechanics = models.ForeignKey(Mechanic, default=1, on_delete=models.DO_NOTHING, blank=True, verbose_name="Mechanic")
status = models.BooleanField(default=True, verbose_name="Open Ticket")
class Meta:
verbose_name_plural = "Tickets"
I need the Customer foreignkey to only display customers of the current user (or 'shopowner') - same thing for mechanic and eventually vehicle but I can figure those out once I know how to get the customer input to display the correct data.
You'll need to customize your form a bit, in order to modify the queryset for that particular field. We also need to pass a user from the view:
forms.py
class TicketForm(ModelForm):
class Meta:
model = Ticket
fields = ['number', 'customer', 'date_created', 'work_description', 'mechanics', 'status']
def __init__(self, user=None, *args, **kwargs):
super().__init__(*args, **kwargs)
if user:
self.fields['customer'].queryset = Customer.objects.filter(shopowner=user)
views.py
def createTickets(request):
form = TicketForm(user=request.user)
# ...
Exactly how you define the queryset is going to depend on how you've defined the relationship between Customer and Shopowner, but this should give you the right approach.

Accessing two apps in one view in Django

I have a Django project with two apps. The first one, market/models.py, includes a Market class and a Share class, where the latter keeps track of all shares bought or sold on any given market, as follows:
class Market(models.Model):
title = models.CharField(max_length=50, default="")
current_price = models.DecimalField(max_digits=5, decimal_places=2)
description = models.TextField(default="")
shares_yes = models.IntegerField(default=0)
shares_no = models.IntegerField(default=0)
b = models.IntegerField(default=100)
cost_function = models.IntegerField(default=0)
open = models.BooleanField(default=True)
def __str__(self):
return self.title[:50]
def get_absolute_url(self):
return reverse('market_detail', args=[str(self.id)])
class Share(models.Model):
user = models.ForeignKey('users.CustomUser',
on_delete=models.CASCADE,
related_name='user_shares',
default=None)
market = models.ForeignKey(
Market,
on_delete=models.CASCADE,
related_name='market_shares',
default=None)
share = models.IntegerField(default=0)
def __str__(self):
return str(self.share)
def get_absolute_url(self):
return reverse('market_list')
The second app, user/models.py, is to create custom users, as follows:
class CustomUser(AbstractUser):
points = models.IntegerField(default=1000)
What I want to do is this: on clicking a button on a template for a specific market, the code will loop through all users with shares in that market to add/subtract the value of each share in their possession from their total points (subtraction would happen when users own negative shares, meaning they owe shares on account of short-selling). The value of each share at that point is simply the current market price.
Here is what I have at the moment, in markets/views.py (the HttpResponseRedirect at the end simply reloads the page):
def resolve(request, pk):
market = Market.objects.get(pk=pk)
market_users = Share.objects.values('user')
for user in market_users:
target_user = CustomUser.objects.get(username=user)
target_user.points += market.current_price * int(user.share)
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
One problem with this (there might be others) is that target_user ends up being of the form <QuerySet [{'user': 1}, {'user': 1}]>, which means Django throws the error CustomUser matching query does not exist.
Any advice would be greatly appreciated!
UPDATE following Higor's suggestion in the comments:
I tried this, which doesn't throw an error, but it fails to update users points:
def resolve(request, pk):
market = Market.objects.get(pk=pk)
market_users = Share.objects.all()
print(market_users) # gives "<QuerySet [<Share: 10>, <Share: 10>]>"
for user in market_users.iterator():
print(user) # gives "10 10"
if user.market == pk:
target_user = CustomUser.objects.get(username=user)
target_user.points += market.current_price * user.share
target_user.save()
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
What you're doing wrong is the way you access your user inside your Share object.
from django.shortcuts import get_object_or_404
def resolve(request, pk):
# if no Market with this pk raises a 404
market = get_object_or_404(Market, pk=pk)
# get shares for the specific market
shares = Share.objects.filter(market_id=pk).select_related('user')
print(shares) # gives "<QuerySet [<Share: 10>, <Share: 10>]>"
for share in shares:
target_user = CustomUser.objects.get(pk=share.user.pk)
target_user.points += market.current_price * share.share
target_user.save()
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
Instead of hardcode your URL you can use reverse like here

A for loop in forms.py fails to load data immediately after it's sent | Python Django

In the forms.py I have a short piece of code which loads the data, but only after I edit print("hello") in it.
The code as follows:
models.py:
class CreateAssignment(models.Model):
user = models.ForeignKey(User, editable=False, blank=True, null=True)
progress = models.CharField(max_length=254, editable=False, blank=True, null=True)
class SetAssignment(models.Model):
mechanic = models.ForeignKey(User, editable=False, blank=True, null=True)
assignment = models.IntegerField(blank=True, null=True)
The mechanic is a permission, plus this mechanic's ID will show in the url of the website, when you will try to set an assignment for this mechanic.
forms.py:
class SetAssignmentForm(forms.ModelForm):
ASSIGNMENT_CHOICES = ()
for item in CreateAssignment.objects.all():
if item.progress == 'Scheduling':
user = User.objects.get(id=item.user_id).username
ASSIGNMENT_CHOICES += (
(item.id, user + ' - ' + str(item.id)),
)
assignment = forms.ChoiceField(choices=ASSIGNMENT_CHOICES, help_text='This is the assignment that you want to apply to this mechanic.')
class Meta:
model = SetAssignment
fields = ('assignment', )
The user_id in this situation is the user that has been set in the CreateAssignment model.
Now the issue is:
The for loop in the SetAssignmentForm works, but it loads data after I put a print in it or when I remove the print from it. Which of course shouldn't really affect the code.
Is there something I'm overlooking? I've been programming in Python Django for 8 weeks now, so if this is a basic program failure, please refer me to a page, because I haven't been able to find any information on this issue.
Thanks for the help.
For the ones that want to know:
views.py:
#login_required
def set_assignment(request):
form = SetAssignmentForm()
id = request.GET.get('id')
user_results = User.objects.filter(pk=id).values()
return render(request, 'pages/set_assignment.html', {'form': form, 'user_results': user_results})
Gif so you can visually see what's happening:
https://drive.google.com/open?id=1u7gfdiS7KitQWNVuvQEEOFJ9wD3q9rY6
You must not write code like this at class level. Anything at that level is only executed once, at definition time - ie when the class is first imported.
If you need to make the values dynamic, you should put the logic inside the __init__ method:
class SetAssignmentForm(forms.ModelForm):
assignment = forms.ChoiceField(choices=[], help_text='This is the assignment that you want to apply to this mechanic.')
def __init__(self, *args, **kwargs):
super(SetAssignmentForm, self).__init__(*args, **kwargs)
items = CreateAssignment.objects.filter(progress='Scheduling').select_related('user')
choices = [(item.id, '{} - {}'.format(item.id, item.user.username)) for item in items]
self.fields['assignment'].choices = choices
(Note, your query logic was very inefficient; my code only hits the database one time.)
However, here you don't even need to do that, because Django already has a form field - ModelChoiceField - that takes its values from the database. You can use a custom subclass of that to show the representation:
class AssignmentField(forms.ModelChoiceField):
def label_from_instance(self, item):
return (item.id, '{} - {}'.format(item.id, item.user.username))
class SetAssignmentForm(forms.ModelForm):
assignment = forms.AssignmentField(queryset=CreateAssignment.objects.filter(progress='Scheduling').select_related('user'))

Categories

Resources