Hi Guys I am trying to figure this out but not having any luck.
So I am showing my events in the homepage which shows how many seats are available, once the user has made a booking I would like to minus that from the amount showing on the homepage.
But I am already stuck at adding all the values up for that event in the booking model to minus from that amount.
So this is what I have
model for events
class Events(models.Model):
ACTIVE = (('d', "Deactivated"), ('e', "Expired"), ('a', "Active"), ('b', "Drafts"),)
ALCOHOL = (('0','No bring own alcohol'),('1','There will be complimentary wine pairing'))
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=50, blank=True, default='')
date = models.DateField()
time = models.TimeField()
price = models.CharField(max_length=240, blank=True, default='')
seats = models.IntegerField()
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
model for bookings
class Bookings(models.Model):
OPTIONS_STATUS = (('y', "Yes"), ('n', "No"), ('p', "Pending"),)
user = models.ForeignKey(User, on_delete=models.CASCADE)
event = models.ForeignKey(Events, on_delete=models.CASCADE)
eventdate = models.DateField()
event_amount = models.CharField(max_length=50, blank=True, default='')
guests = models.IntegerField()
bookingstatus = models.CharField(max_length=50, default='p', blank=True, choices=OPTIONS_STATUS)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
my homepage how I get my data into a loop form the view
today = datetime.now().strftime('%Y-%m-%d')
events_list_data = Events.objects.filter(active='a').filter(Q(date__gte=today)|Q(date=today)).order_by('date')
How I am trying to show this in my template
{% for event_list in events_list_data %}
SHOW WHAT EVER DATA I AM SHOWING NOT NEEDED FOR HELP ON
{% for bookingguests in
event_list.bookings_set.all %}
{{ bookingguests.guests }}
{% endfor %}
Seats Left
{% endif %}
Generally, purpose of templates is not to implement logic. All the logic should go into your views. I would recommend you to do that in your views and either store it in a dict or a list and send it to front-end.
Once the user made a booking, if you want to modify the value on the HTML without reloading, you may need to use jQuery/javascript. Otherwise, if you are fine with reloading the page by rendering it again with calculations from the backend.
By using jQuery:
$("#balance-id").html(logic to get the balance)
By Calculating in views:
from django.db.models import Sum
user_balance = user.balance - events_data.aggregate(Sum('price'))
return render('path/to/template', {'events_list': events_list_object, 'user_balance':user_balance})
In the template:
{{user_balance}} seats left
Let me know in case of any questions.
Note: If you want to write some logic into your templates, use template tags. It can help you with whatever it can with its limited functionality.
Related
I'm trying to create a dashboard for orders placed by a customer. I've got multiple tables, but the two I'm dealing with is "Order" and "Order_Detail". From the "Order" table, I need to display Customer, Status, and Required_date, from the "Order_Detail" table, I need Product. I'm able to access the data but I can figure out how to display all the records at the same time on one page.
models.py
class Order(models.Model):
STATUS = (
('New', 'New'),
('Ready For Fullfillment', 'Ready For Fullfillment'),
('Fullfilled Ready For Delivery', 'Fullfilled Ready For Delivery'),
('Out For Delivery', 'Out For Delivery'),
('Delivered', 'Delivered'),
)
order_date = models.DateTimeField(auto_now_add=True, null=True)
required_date = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
note = models.CharField(max_length=1000, null=True, blank=True)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.customer.name
class Order_Detail(models.Model):
orderNumber = models.ForeignKey(Order, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
pounds = models.IntegerField(null=True)
ounces = models.IntegerField(null=True)
container = models.ForeignKey(Container, null=True, on_delete=models.SET_NULL)
lot_code = models.CharField(max_length=200, null=True, blank=True)
note = models.CharField(max_length=1000, null=True, blank=True)
In my views.py, I'm playing with the following code:
print('TEST2')
o = Order.objects.all()
o_notdelivered = Order.objects.exclude(status='Delivered')
for e in o_notdelivered:
print('Order ID:', e.id)
order_detail_data = serializers.serialize("python", Order_Detail.objects.all().filter(orderNumber=e.id))
print('order_detail_data:', order_detail_data)
With that code, I'm able to get the ORDER data and related ORDER_DETAIL data, but I can't figure out how to put the fields I need together and send it to my template. Please note that their will be multiple orders and order_details that will need to go to the template.
Basically, in the end, I want, on my dashboard a table that looks like this:
|Customer|Product|Required Date|Status|
|-|-|-|-|
|C1|Product1|date here|New|
|C2|Product3|date here|New|
In your template (.html file) you have to access this variables, for example, if you want to show the status of all packages, then, in the html file you should write something like:
{% for object in o %} <!-- Works like in python-->
<h1>{{object.status}}</h1>
<!-- Do this for all other attributes-->
{% endfor %} <!-- Must close 'for loop'-->
use this query in your views Order_Detail.objects.all() and pass the context.
views.py
order_details = Order_Detail.objects.all()
context = {'order_details':order_details }
....your others code
then in your html:
{{order_details.product}} #accessing data from your Order_Detail model
{{order_details.orderNumber.status}} #accessing data from your Order model via foreignkey
I recently found that too much SQL query optimization issue. django-debug-tool reported hundreds of similar and duplicate queries. So, I'm trying to figure out the best efficiency of Django ORM to avoid unnecessary Queryset evaluation.
As you see the below Store model, a Store model has many Foreign key and ManyToManyFields. Due to that structure, there are many code snippets doing the blow on HTML template files such as store.image_set.all or store.top_keywords.all. Everything starts with store. In each store detail page, I simply pass a cached store object with prefetch_related or select_related. Is this a bad approach? Should I cache and prefetch_related or select_related each Foreign key or ManyToManyField separately on views.py?
HTML templates
{% for img in store.image_set.all %}
{{ img }}
{% endfor %}
{% for top_keyword in store.top_keywords.all %}
{{ top_keyword }}
{% endfor %}
{% for sub_keyword in store.sub_keywords.all %}
{{ sub_keyword }}
{% endfor %}
views.py
class StoreDetailView(View):
def get(self, request, *args, **kwargs):
cache_name_store = 'store-{0}'.format(store_domainKey)
store = cache.get(cache_name_store, None)
if not store:
# query = get_object_or_404(Store, domainKey=store_domainKey)
query = Store.objects.all().prefetch_related('image_set').get(domainKey=store_domainKey)
cache.set(cache_name_store, query)
store = cache.get(cache_name_store)
context = {
'store': store,
}
return render(request, template, context)
models.py
class Store(TimeStampedModel):
categories = models.ManyToManyField(Category, blank=True)
price_range = models.ManyToManyField(Price, blank=True)
businessName = models.CharField(unique=True, max_length=40,
verbose_name='Business Name')
origin = models.ForeignKey(Origin, null=True, on_delete=models.CASCADE, blank=True)
ship_to = models.ManyToManyField(ShipTo, blank=True)
top_keywords = models.ManyToManyField(Keyword, blank=True, related_name='store_top_keywords')
sub_keywords = models.ManyToManyField(SubKeyword, blank=True, related_name='store_sub_keywords')
sponsored_stores = models.ManyToManyField(
'self', through='Sponsorship', symmetrical=False, related_name='sponsored_store_of_store')
similar_stores = models.ManyToManyField(
'self', through='Similarity', symmetrical=False, related_name='similar_store_of_store')
shortDesc = models.TextField(blank=True, verbose_name='Short Description')
longDesc = models.TextField(blank=True, verbose_name='Long Description')
returnPol = models.TextField(verbose_name='Return Policy', blank=True)
returnUrl = models.CharField(max_length=255, null=True, blank=True, verbose_name='Return Policy URL')
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, editable=False)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE,
related_name='stores_of_created_by', null=True, blank=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE,
related_name='stores_of_updated_by', null=True, blank=True)
I really wouldn't advise custom caching/performance optimisation, unless it's a very last resort. Django has great docs on querysets and optimisation - if you follow those, it should be rare for you to experience major performance issues that require custom workarounds.
I think the issue here is that you're printing your objects in a template and hence calling their str() method. There's nothing wrong with this, but I'd check what variables you're using in your str() methods. I suspect you're referencing other models? I.e. the str() method in your image model (or whatever) is doing something like image.field.other_field. In this case, your query should look like:
queryset = Store.objects.prefetch_related('image_set__field')
Your final queryset may look like:
queryset = Store.objects.prefetch_related('image_set__field1', 'image_set__field2', 'top_keywords__field3', ...)
Note that you can still pass this into get_object_or_404 like so:
get_object_or_404(queryset, pk=<your_stores_id>)
Hope this helps.
I'm trying to get my head around how Django understands m2m relationships, in SQL you would just add some joins through the intermediate table.
I have a Container which contains various Samples. A Sample can be spread over various Containers.
So in my container I add a alias samples m2m field (essentially a book mark to the other table).
What I can do is get a single Container and display the form information, I would like to add the Sample columns to the form, if I do this for the samples m2m field it returns a multifield, but how do I access the other related fields through the m2m sample_id >=< container_id ?
class Container(models.Model):
container_id = models.AutoField(primary_key=True)
samples = models.ManyToManyField(Sample, through='JoinSampleContainer', through_fields=('container_id', 'sample_id'), related_name='container')
location_id = models.ForeignKey(Location, db_column='location_id', on_delete = models.PROTECT)
icon_desc = models.ForeignKey(Icon, db_column='icon_desc', null=True, blank=True, default='Box',on_delete = models.PROTECT)
container_name = models.CharField(max_length=50, blank=True, null=True)
container_type = models.CharField(max_length=50, blank=True, null=True)
In my Sample table I add the containers alias to act as a bookmark to the other table
class Sample(models.Model):
sample_id = models.AutoField(primary_key=True)
containers = models.ManyToManyField(Container, through='JoinSampleContainer', through_fields=('sample_id', 'container_id'), related_name='sample')
sample_number = models.IntegerField()
material_type = models.CharField(max_length=200, default='', blank=True, null=True, choices = MATERIALS)
weight = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500, default='', blank=True, null=True)
recovery_method = models.CharField(max_length=200, default='', blank=True, null=True, choices = RECOVERY_METHODS)
comments = models.CharField(max_length=1000, default='', blank=True, null=True)
In this case I am managing the through table:
class JoinSampleContainer(models.Model):
id = models.AutoField(primary_key=True)
container_id = models.ForeignKey(Container, db_column='container_id', on_delete = models.PROTECT)
sample_id = models.ForeignKey(Sample, db_column='sample_id', on_delete = models.PROTECT)
So now I want to display the contents of a single container through a form. I have the url's setup to pass the container_id.
# views.py
def containercontents(request, pk):
post = get_object_or_404(Container, pk=pk)
# objects = Container.samples.all()
if request.method == "POST":
form = ContainerContentsForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
#post.user = request.user
#post.datetime = datetime.datetime.now()
post.save()
return redirect('allcontainer')
#, pk=post.pk)
else:
form = ContainerContentsForm(instance=post)
return render(request, 'container/containercontents.html', {'form': form})
The Form
# form.py
class ContainerContentsForm(forms.ModelForm):
class Meta:
model = Container
fields = (
'location_id',
'container_name',
'container_type',
'icon_desc',
'samples',
)
N.B. The samples seems to list everything regardless of the container.
Then the html
# html
contents
which passes to:
# html
<div class="">
{{ form }}
</div>
Your models are defined wrongly: You should not define the ManyToManyField on both models, only on one of them. So remove the containers field on Sample and only keep it on Container. Set the related_name to "containers" (plural). That way the relationship Container -> Sample is container.samples.all() and the reverse one is sample.containers.all().
Now the purpose of a form is to allow you to select which Samples you want to associate to a Container. So by default the field will be represented by a ModelMultipleChoiceField. The already associated Samples should be pre-selected when you initialise the form with a Container instance.
You can narrow the samples to select from by specifying the queryset for the field, by overriding the default field in the form:
class ContainerContentsForm(forms.ModelForm):
class Meta:
# same code here
samples = forms.ModelMultipleChoiceField(
queryset = Sample.objects.filter(...)
)
You say you want to "display the contents of a Container through the form", if you just want to display, why use a form? To just display the contents, loop through the related samples and display them:
{% for sample in form.instance.samples.all %}
{{ sample.sample_id }}
{% endfor %}
Note: You should rename your ids to id. sample.sample_id is bad programming style. But I already told you that.
class PlannedOTList(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
date_added = models.DateTimeField(auto_now_add=True)
planned_surgery = models.TextField(verbose_name='diagnosis and planned surgery', blank=True) # decided by the committee
planned_date_of_surgery = models.DateField('date of surgery', null=True, blank=True)
planned_date_of_admission = models.DateField('date of admission', null=True, blank=True)
remarks = models.TextField(blank=True)
surgery_set = models.BooleanField('required surgery set', default=False)
# to_be_admitted = models.BooleanField(default=False)
hide = models.BooleanField(default=False)
objects = PlannedOTListQS.as_manager()
class Meta:
db_table = 'planned_ot_list'
ordering = ['-date_added']
class Admission(models.Model):
# general info
date_admission = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
class OperationNotesList(models.Model):
admission=models.ForeignKey(Admission,on_delete=models.CASCADE,null=True)
#patient=models.ForeignKey(Patient,on_delete=models.CASCADE)
date_added=models.DateTimeField(auto_now_add=True)
procedure_code=models.CharField(max_length=7)
diagnosis_code=models.CharField(max_length=10)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, related_name='op_created_by')
pre_operation_list=models.CharField(max_length=70,blank=True)
intra_operation_list=models.CharField(max_length=70,blank=True)
post_operation_list=models.CharField(max_length=70,blank=True)
is_done=models.BooleanField(default=False)
class Meta:
db_table='operationNotesList'
class Patient(models.Model):
patientid_generated_part = models.CharField(max_length=5, default='', blank=True)
date_recorded = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(auto_now=True, null=True)
first_name = models.CharField(max_length=50)
class Meta:
db_table = 'patients'
ordering = ['-modified']
HTML Code:
<div class="row">
<div class="col-xs-6 col-md-3"><label >Proposed Operation:  
{{ operationnoteslist.admission.patient.planned_ot_list.planned_surgery }}</label></div>
<div class="col-xs-6 col-md-3"><label >Weight:  
{{ operationnoteslist.admission.weight }} (kg)</label></div>
<div class="col-xs-6 col-md-3"><label >Height:  
{{ operationnoteslist.admission.height }} (cm)</label></div>
<div class="col-xs-6 col-md-3"><label >BMI:  
{{ operationnoteslist.admission.bmi }}</label></div>
</div>
the html code above has the main model operationnoteslist.
I am trying to get values from planned_ot_list. I don't know what I am missing.
I thought the way to go is: MyownModelTable.foreignTablename.foreignTablename.field
The Proposed operation does not retrieve any values.
(As reply to the comment: There is no need for a planned_ot_list in the Patient model.)
Reverse relations (one to many) have by default a _set suffix. Also, in your PlannedOTList model, patient has not the unique flag so a patient can have several of those related to them. And on top, the model relation name in lowercase has no underscores (camel case is simply lower cased). So the reverse relation name should be:
patient.plannedotlist_set
(You can print out the available properties using dir(patient), the output will include the reverse relation properties.)
This returns a query manager and you cannot simply write patient.plannedotlist_set.planned_surgery. Instead, you have to decide whether to display the complete list or only one of its entries. If they have a natural order and you want to use the first or last, you can do this:
patient.plannedotlist_set.first # in the template or first() in view
patient.plannedotlist_set.last
To iterate over all of them use:
patient.plannedotlist_set.all # template or all() in view
Note that you should give the PlannedOTList an ordering to make this work, either by adding a Meta property like this:
Meta:
ordering = ('field1', 'field2', ...) # use '-field1' for reverse
Or, if the ordering is dependent of the view, order in the view and add the list to the template context explicitly.
I'm trying to get django-haystack (using a xapian backend) to index my model here for search, by the name and description fields.
I have a subclass of Item, Device, which adds a manufacturer field.
The Item model is defined thusly:
class Item(models.Model):
name = models.CharField(max_length=255, unique=True)
description = models.TextField(null=True, blank=True)
compatible_with = models.ManyToManyField('self', null=True, blank=True)
often_with = models.ManyToManyField('self', null=True, blank=True)
created_by = models.ForeignKey(User, null=True, blank=True, related_name='created_by')
verified = models.BooleanField(default=False)
verified_by = models.ForeignKey(User, null=True, blank=True, related_name='verified_by')
date_created = models.DateField(auto_now_add=True)
slug = models.SlugField(max_length=300, null=True, blank=True)
My subclass of django-haystack’s SearchIndex looks like this:
class ItemIndex(SearchIndex):
text = CharField(document=True, use_template=True)
name = CharField(model_attr='name')
description = CharField(model_attr='description')
site.register(Item, ItemIndex)
I have set up this template, in templates/search/indexes/catalog/item_text.txt:
{{ object.name }}
{{ object.description }}
What do I add to item_text.txt such that the manufacturer field gets indexed, if and only if the model object is an instance of Device?
{% if device.manufacturer %}
{{ device.manufacturer }}
{% endif %}
... the Haystack tutorial is a bit confusing on this subject (you don't actually have to use a text-file template, for one) but the basic idea is that Haystack's engine goes to town on whatever text data is in this template.
... Actually, it goes to town on whatever is in the response you send it, but if you've got the template set up you can use whatever Django template logic you want in there.
(note that the if template tag was a bit of a dog's breakfast prior to Django 1.2; if you're stuck on an earlier Django version you may have to tweak the syntax, but the principle is the same.)