How can I display a view based on a database value - django

I want to use one view (URL) for 2 conditions.
In my application, "owners" create daily plans for routes they manage, and update the plans/results throughout the day.
class DailyRoute(models.Model):
owner = models.ForeignKey(Owner)
route = models.ForeignKey(Route)
driver = models.ForeignKey(Driver)
stops = models.PositiveSmallIntegerField(default=0, ...
on_duty_hours = models.TimeField(default=datetime.time...
date = models.Datefield(...
finalized = models.Boolean(...
Essentially, there are 3 database conditions, 2 of which I'm trying to use for a view:
No database row for the date/route. This means that the owner hasn't created a plan for the day. (e.g. if DailyRoute.objects.filter(stage = 0).count() == 0:...)
A database row for the date/route with finalized = False. This means that a plan has been created for the day for the date/route pair and can be edited.
(e.g. DailyRoute.objects.filter(stage = 0).count() >0 )
A database row for the date/route with finalized = True. This means that a plan/updates for the day are complete and no further edits are allowed. (e.g. if DailyRoute.objects.filter(stage = 1).count() > 0:...)
As a daily activity, I want the user to go to a URL (e.g. /account/daily) and be presented with one of these views:
a) If no owner routes (point 1 above), provide an "Add" button to add a row for each owned route for a specific date (i.e. next business day). On success, display the DailyRoute List as per b) below.
b) If owner routes exist in the 0 state, display the list (i.e. don't display the "Add" button.)
Note that an owner can never have more than one date / route pair in the 0 state. They must complete the day's activities on 0 state routes before they can plan the next days routes.
Alternatively, it would be acceptable to have View with a disabled "Add" button and a list of routes, if routes are in the 0 state. Conversely, the "Add" button would be enabled and an empty list of routes, if no routes are found.
Right now I can do this with separate URLs, one for add daily plan, the other to display a list of routes in stage=0, but it would be much better to do this all on the same URL.
I can't figure out how/where to add a filter to a view to do this.
Thanks in advance for guidance.

Well, sounds like a simple if/else statement would do the trick:
class YourView(View):
if first_condition:
return render('first_template')
else if second_condition:
return render('second_template')
else:
return render('third_template')
Or, if you want to use one template, you can do this if/else inside your template. I also suggest that you send that flag from your view:
class YourView(View):
...
routes_exist = DailyRoute.objects.filter(stage = 0).exists()
return render('template.html', {'routes_exist': routes_exist})
Then in your template:
{% if routes_exsist %}
<button> Add </button>
{% endif %]
Hope it helps!

Related

Django - Field by Field Restrictions on Which Users Can view Certain Fields

I'm learning Django and building a simple CRUD application. I have a model for cars, and this contains a number of fields. When a user loads a car page, I'd like some fields to be displayed and others hidden, depending on whether the user has a high enough score for the car they are viewing. So for each field (engine, wheels, headlights, etc), or for some groups of fields, there would be a corresponding visibility score. If the user's score for that particular car exceeded the visibility for a particular field, then the data for that field would be displayed in the view.
I could add a DecimalField variable for each component to denote this minimum score, the Car model would have a calc_score(user) method. In the view the current user's score would be compared against each of these, but I'm guessing there may be a better way to do this. Can anyone recommend a better approach?
Thank you.
You should just pass in the user's score as context when rendering the page from your views.py. It would look something like this:
def car_page_view(request):
current_user_score = getUserScore()
context = {
'user_score': current_user_score
}
return render(request, 'car-page.html', context)
Then, in your html, put a check like this to only show certain elements:
{% if user_score > 10 %}
<text>This text is only visible to users with scores higher than 10.</text>
{% endif %}
This is better than, say, loading all html elements and setting certain elements to "hidden". Instead, this causes the html you want hidden to never be loaded at all. So even if they use the inspect tool they won't see it :)

Comparing Date to Minimum Future Value in Other Model

I have two django models that define:
Item = A set of items with an expiry date.
Event = A set of events that have a start and end date.
My aim is that when the item is displayed, its expiry date is shown conditionally formatted, based on whether that item expires after the next event's end date but before the following events end date (so warning when it's due to expire.)
The problem becomes, how best to manage this feat?
If I was directly accessing the database, I'd be using subqueries to get the minimum end date still in the future, and then comparing that to the expiry date on an if basis to swap the formatting.
From research, I'm coming to the conclusion that this is best handled in the view logic, rather than trying to set a method in either of the models, but I don't know how best to get this to splice together so I can return the value of my minimum future date and my itemlist object from the Item model.
The current view is pretty simple at this stage (it will have more filtering options later):
def itemlist(request):
item_list = Item.objects.all
return render(request, "itemlist.html", {'item_list': item_list})
but I cant see a way of easily returning a django equivalent of something like what I'd do in straight SQL:
select item from items where status != expired and expiry_date <= (select min(end_date) from events where end_date >= getdate() )
EDIT: Since I've written this, I've realised the comparison for what I want is a little more complex, as it's not the minimum date, it's the next to minimum.
For Item A, expiry_date 01/05/19
Event A: end_date 25/04/19
Event B: end_date 10/05/19
What I need it to do is check the events when reading back the item list, see that Item A's expiry date is after the next event.end_date for event A, but is before the event.end_date for event B, so set a flag for using conditional formatting on the template's expiry date display.
Eventually, I suppose, the wish list is to also be able to say for every item "what's the latest event I can renew this item before it expires if there's an event in the list after its expiry time."
I could not completely understand your requiremets from your description, but you can use subqueries in Django as well. If you filter like this:
now = datetime.datetime.utcnow()
Item.objects.annotate(last_event_time=Subquery(Event.objects.filter(end_date__gt=now).values('end_date').order_by('-end_date')[:1]))
Each item in the resulting queryset will have last_event_time field, which would keep the latest event end_date field.
You can also use this field in further filtering, using F expressions:
Item.objects.annotate(last_event_time=Subquery(Event.objects.filter(end_date__gt=now).values('end_date').order_by('-end_date')[:1])).filter(expiry_date__lte=F('last_event_time'))

add custom product statuses in opencart admin

By default in opencart we have 2 product statuses (which we can use also in admin to filter products) - enabled and disabled.
I need to add a few more custom statuses, which will be just for my team which is working over the products (for example i want to add need description status, products with the custom statuses will not show in the front end (like disabled) so if the product is market with it, the team who is working on product descriptions will easy filter only the products that need descriptions).
I hope i explained clearly as well...Thank you...
If you look into the language file of product admin/language/language_name/catalog/product.php, there is $_['text_enabled'] and $_['text_disabled'], you can add $_['text_need_description'].
In category.php and product.php controllers you will find
$data['text_enabled'] = $this->language->get('text_enabled');
$data['text_disabled'] = $this->language->get('text_disabled');
Next to them, you can add
$data['text_need_description'] = $this->language->get('text_need_description');
You can check occurrences of 'enabled' and change accordingly. You also need to change the relevant templates and models.
In database, status is saved as 1 for enabled and 0 for disabled, you can save the value 2 for 'need description'.
When the products are fetched to be displayed to the customer on front-end, only the products with status 1 are fetched so you won't have to change that part.

Pass values between pages in Oracle Apex

I am developing a mobile application that should allow a student to search for job vacancies. I have used the wizard to create a form with a list view. The list view will only show job titles which are not past their closing date (available jobs)
When a job title is clicked it redirects to the form where the student can view further job details. These values are passed automatically by the wizard.
Now while this whole thing is great I need information from 3 different tables and the wizard won't help me with that.
I have created a list view based on an sql query and also a form based on an sql query. I have tried to create automatic fetch processes to pass the values from my list view to the form view but nothing I have tried has worked. I carefully analysed the forms created by the wizard to see how it could be done but nothing worked for me and I would really love to do it in this way.
For reference this is the sql code I used for the list view (and it's the same for the form view except for the where clause )
T1.JOB_TITLE,
T1.SALARY,
T1.JOB_DESCRIPTION,
T1.START_DATE,
T1.CLOSING_DATE,
T1.METHOD_ID,
T3.METHOD_NAME,
T1.SITE_ID,
T2.CITY,
T2.ADDRESS_FIRST_LINE,
T2.EMAIL,
T2.COMPANY_NAME
FROM JOB T1
JOIN SITE T2 ON (T2.SITE_ID = T1.SITE_ID)
JOIN APPLICATION_METHOD T3 ON (T3.METHOD_ID = T1.METHOD_ID)
Where (T1.Closing_Date >(Select Current_Date from dual))
There are really two ways you could solve this:
1) If you can simply pass the values you need to the form page, edit the values of your Form region, and open up the "Link Target" attribute (this is assuming you're using APEX 5 Page Designer). There, you will be able to pass in multiple values to items on your Form page.
2) If, instead, you need to derive these values on your Form page, add an After Header process on your form page and do the lookups from your other tables in this process, using PL/SQL. You can use the bind variable syntax to reference your items and update session state. For example:
begin
for c1 in (select val1, val2 from my_other_table where id = :P3_ID) loop
:P3_ITEM1 := c1.val1;
:P3_ITEM2 := c1.val2;
exit;
end loop;
end;
I managed to add the additional columns by adding more items and selecting an Sql-query that returns a single row from the item attributes (Source).
So in order to get method_name rather than an ID which would be irrelevant for the end user I used this code:
SELECT METHOD_NAME FROM APPLICATION_METHOD
WHERE (METHOD_ID = :P3_METHOD_ID)
I am fairly certain that it might not be a great solution if you have a lot of columns that need to go through but it was easy to understand and implement for a few additional columns.

Django: Deleting user selected entries from a database

I have a Django app that displays a list of rows in a table to the user. Each row maps to an entry in a database. I want to let the user select the rows they would like deleting by adding a checkbox to the end of each row and a delete button ( similar to how gmail lets you delete multiple mail messages). I can't quite figure out how to write the view in terms of finding out which rows were selected and how to map these to the IDs of the entries that need deleting from the database. A simple code snippet showing how to do this would be greatly appreciated.
UPDATE:
I've found this code snippet that I think should do the trick
You can use the CheckboxSelectMultiple widget to auto-generate the corresponding HTML code so you don't have to do it manually.
You can define your form like so:
class UsersForm(forms.Form):
users = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=[QuerySetIterator(Users.objects.all(), "", False)], label="")
Another advantage is that you also get validation for free.
Create a formset and pass can_delete = True to the constructor. Then, in the template,
{{formset}}