Calculated fields (property) in crispy forms - django-models

It is possible to render calculated fields from model (#property) as readonly field or using HTML layout in crispy-forms?
Thanks in advance for your answers.

Pass your model instance to template using your views and get property value in template
models.py
from datetime import date
class DemoModel(models.Model):
name = models.CharField(mx_length=23)
dob = models.DateTimeField()
#property
def age(self):
return date.today().year - self.dob.year
views.py
def demoview(request):
from .models import DemoModel
instance = DemoModel.objects.first()
return render(request, 'index.html' ,{'instance':instance})
HTML
<p>DOB: {{ instance.dob }}</p>
<p>AGE: {{ instance.age }}</p>

Related

Lightning-record-view form is not displaying the record with the id that is fetch from an apex class. Salesforce LWC,Apex

I have a record view for which the id is from apex class and then wired it and assigned to a variable, but the record is not displaying. below is my code.
apex class to get the record id of the record owned by the user
#AuraEnabled(cacheable=true)
public static Wallet__c getWalletInfo(){
String userId = UserInfo.getUserId();
return [SELECT Id From Wallet__c WHERE OwnerId =: userID LIMIT 1];
}
.js class - assigned the data to getId
import getWalletInfo from '#salesforce/apex/CustomWalletHandler.getWalletInfo';
import wallet from '#salesforce/schema/Wallet__c';
import walletName from '#salesforce/schema/Wallet__c.Name';
import walletBalance from '#salesforce/schema/Wallet__c.balance__c';
import walletFrom from '#salesforce/schema/Wallet__c.added_from__c';
export default class CustomWallet extends LightningElement {
objectName = wallet;
name = walletName;
balance = walletBalance;
from = walletFrom;
getId;
isUser = true;
#wire (getWalletInfo,{})
walletData({error, data}){ //data is record Id
if(data){
this.getId = data;
console.log(this.getId);
this.isUser = false;
}else if(error) {
// error handling
console.error(error.body.message);
}
}
}
html - if user has no recordc Create Wallet will display and if user has record only the record will display.
<template>
<lightning-card>
<lightning-tabset>
<template if:true={isUser}>
<lightning-tab label="Create a Wallet">
<lightning-record-form
object-api-name="Wallet__c"
columns="2"
layout-type="Full"
></lightning-record-form>
</lightning-tab>
</template>
<template if:false={isUser}>
<lightning-tab label="My Wallet">
<lightning-record-view-form
record-id={getId}
object-api-name={objectName}>
<div class="slds-box">
<lightning-output-field field-name={name}>
</lightning-output-field>
<lightning-output-field field-name={balance}>
</lightning-output-field>
<lightning-output-field field-name={from}>
</lightning-output-field>
</div>
</lightning-record-view-form>
</lightning-tab>
</template>
</lightning-tabset>
</lightning-card>
I think you overcomplicated it a bit. What do you get when you put simpler references to object & fields?
<lightning-record-view-form
record-id={getId}
object-api-name="Wallet__c">
<div class="slds-box">
<lightning-output-field field-name="Name"></lightning-output-field>
<lightning-output-field field-name="Balance__c"></lightning-output-field>
<lightning-output-field field-name="Added_From__c"></lightning-output-field>
</div>
</lightning-record-view-form>
And your apex method is returning whole Wallet__c object, not just the Id. With just 1 field populated but still. You can tell by seeing curly braces in your console.log's output. So you need either this.getId = data.Id; in JS or record-id={getId.Id} in HTML. Or make Apex return just an Id variable (and null if no results found I guess?)

Cannot make a model #property def-as-field work with wagtail 2.0

I'm using Wagtail 2.0 with a custom Block that has the following code:
class LinkButtonBlock(blocks.StructBlock):
label = blocks.CharBlock()
URL = blocks.CharBlock()
styling = blocks.ChoiceBlock(
choices=[
('btn-primary', 'Primary button'),
('btn-secondary', 'Secondary button'),
('btn-success', 'Success button'),
('btn-info', 'Info button'),
('btn-warning', 'Warning button'),
('btn-error', 'Error button'),
],
default='btn-info',
)
outline = blocks.BooleanBlock(
default=False
)
#property
def css(self):
btn_class = self.styling
if self.outline is True:
btn_class = btn_class.replace('btn-', 'btn-outline-')
return btn_class
class Meta:
icon = 'link'
template = 'testapp/blocks/link_button_block.html'
If I then try to access this css "property" in my template, nothing seems to happen. Putting a print(self) as first line inside the css def also shows nothing on the console suggesting the function never even gets called.
Using the following template:
{% load wagtailcore_tags %}
<a class="btn {{ block.value.css }}" href="{{ block.value.URL }}">{{ block.value.label }}</a>
Simply yields:
<a class="btn " href="actual.url.from.instance">actual.label.from.instance</a>
Also, block.value.styling and block.value.outline on their own work just fine, so... what am I doing wrong here?
The thing that's tripping you up is that the value objects you get when iterating over a StreamField are not instances of StructBlock. Block objects such as StructBlock and CharBlock act as converters between different data representations; they don't hold on to the data themselves. In this respect, they work a lot like Django's form field objects; for example, Django's forms.CharField and Wagtail's CharBlock both define how to render a string as a form field, and how to retrieve a string from a form submission.
Note that CharBlock works with string objects - not instances of CharBlock. Likewise, the values returned from StructBlock are not instances of StructBlock - they are a dict-like object of type StructValue, and this is what you need to subclass to implement your css property. There's an example of doing this in the docs: http://docs.wagtail.io/en/v2.0/topics/streamfield.html#custom-value-class-for-structblock. Applied to your code, this would become:
class LinkButtonValue(blocks.StructValue):
#property
def css(self):
# Note that StructValue is a dict-like object, so `styling` and `outline`
# need to be accessed as dictionary keys
btn_class = self['styling']
if self['outline'] is True:
btn_class = btn_class.replace('btn-', 'btn-outline-')
return btn_class
class LinkButtonBlock(blocks.StructBlock):
label = blocks.CharBlock()
URL = blocks.CharBlock()
styling = blocks.ChoiceBlock(choices=[...])
outline = blocks.BooleanBlock(default=False)
class Meta:
icon = 'link'
template = 'testapp/blocks/link_button_block.html'
value_class = LinkButtonValue

Filter items from an InlinePanel in wagtail

For a small listing of events I used an InlinePanel in my page model. Now I would like to filter these events by date, like I would do when using a #property with subpages: date__gte=date.today() for only displaying the future events on the page TourdatenIndexPag. How to achieve that?
My implementation:
class EventItem(LinkFields):
date = models.DateField("Datum")
...
panels = [FieldPanel('date')]
class Meta:
abstract = True
class TourdatenPageEventItem(Orderable, EventItem):
page = ParentalKey('md.TourdatenIndexPage', related_name='event_items')
class TourdatenIndexPage(Page):
...
content_panels = Page.content_panels + [
InlinePanel('event_items', label="Events"),
]
Where and how could these event_items be accessed and filtered?
Create a method on your page model to return the queryset you want:
class TourdatenIndexPage(Page):
def future_event_items(self):
return self.event_items.filter(date__gte=date.today())
Then, on your template, you can refer to self.future_event_items:
{% for event in self.future_event_items %}
<li>{{ event.date }}</li>
{% endfor %}

Django-cms plugin mptt filtering by node to display new subtree, based on config

I am trying to implement a plugin for django-cms that shows a tree of of links. What I want to do is filter this tree based on what config the user chooses in my CMS. So based on the node he chooses in the config I want to be able to display only that sub-tree.
Here is my models.py
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from cms.models.pluginmodel import CMSPlugin
class Section(MPTTModel):
name = models.CharField(max_length=25, unique=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
class MPTTMeta:
order_insertion_by = ['name']
def __str__(self):
return self.name
class SectionConfig(CMSPlugin):
root_shown = models.ForeignKey("Section")
title = models.CharField(default="Usefull Links", max_length=25)
Here is my cms_plugins.py:
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from cms.models.pluginmodel import CMSPlugin
from django.utils.translation import ugettext_lazy as _
from links_plugin.models import Section, SectionConfig
class LinksPlugin(CMSPluginBase):
name = _("Links Tree Plugin")
model = SectionConfig
render_template = "links.html"
cache = False
def render(self, context, instance, placeholder):
context['instance'] = instance
context['nodes'] = Section.objects.all()
return context
plugin_pool.register_plugin(LinksPlugin)
and here is my templates/links.html
<div class='container-fluid'>
<h1>Liens Utiles</h1>
{% load mptt_tags %}
<ul class="root">
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</div>
So my issue is giving the right set of nodes to my context. So in my cms_plugins.py id like to change
context['nodes'] = Section.objects.all()
to a filter that would build the subtree based on my
root_shown = models.ForeignKey("Section")
The problem is I don't know how to use the FK to reference my Section object and find my new root Section. From then I thought that I could use the get_descendants(include_self=True) to rebuild this new sub-tree and display that list of nodes. Am I wrong? How to I reference my desired node?
If possible ELI5
You'll want something like this:
contect['nodes'] = instance.root_shown.get_descendants(include_self=True)

Spring MVC, Angular AngularJS drop-down list - problems on persist ManyToOne

Problem: I have a Purchase Order table and Country table which primary key is a foreign key in my PO table. On the front end I have a form (angularJS) used for creation of a new PO with a bunch of fields and about 9 drop-down list fields form where user can select whatever info is required for the PO.
For the sake of the example I will use the Country drop-down. (All drop-downs are getting populated from the DB).
The problem I have is with the persistence. After submitting the form, if I use the debugger and I check the Purchase Order object that is being passed to the service all my drop downs objects are null, except the other normal input fields which belong to the PO table.
I think the problem is Angular, If I check the network tab in my chrome browser under developer tools I see the country being passed as countryData:2. Thing is I am new to Angular so I am bit confused at this stage on how I should handle this as data is coming from the drop-down list and how I should return the country object. Here http://tinypic.com/r/2rd9pxl/8 I put a screenshot of my network tab from the browser which show the from Data that is being posted.
Populate the country drop-down list
<div class="control-group">
<label class="control-label">*Country</label>
<div class="input-append">
<div data-ng-init="getCountryDataFromServer()">
<b>Person Data:</b> <select id="countryData" ng-model="contact.countryData">
<option value="">-- Select Countries --</option>
<option data-ng-repeat="country in countries" value="{{country.countryId}}">{{country.countryname}}</option>
</select><br>
</div>
</div>
<div class="input-append">
<label>
<span class="alert alert-error"
ng-show="displayValidationError && newContactForm.countryData.$error.required">
<spring:message code="required"/>
</span>
</label>
</div>
</div>
Model
#Entity
#Table(name = "PURCHASEORDER",schema = "POTOOL")
#Audited
public class PurchaseOrder {
#Id
#GeneratedValue
private int id;
private String tower;
private Double revenue;
//other properties of the PO
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "country_id")
private Country country;
//Other ManyToOne relationships
//Getter and setters
Controller
#RequestMapping(method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> create(#ModelAttribute("contact") PurchaseOrder purchaseOrder,
#RequestParam(required = false) String searchFor,
#RequestParam(required = false, defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
Locale locale) {
purchaseOrderServiceImpl.save(purchaseOrder);
if (isSearchActivated(searchFor)) {
return search(searchFor, page, locale, "message.create.success");
}
return createListAllResponse(page, locale, "message.create.success");
}
Service
public void save(PurchaseOrder purchaseOrder) {
purchaseOrderRepository.save(purchaseOrder);
}
Repository
public interface PurchaseOrderRepository extends
PagingAndSortingRepository<PurchaseOrder, Integer> {
}
I don't think there is any issue because of angular since you have defined ng-model="contact.countryData" for dropdown and option has value from value="{{country.countryId}}". When you submit value country.countryId is going to server which is absolutely fine. I think you should have conversion mechanism which will convert data from UI to Hibernate Entity(i.e. PurchaseOrder). Generally DTO(Data transfer Object) is used to get data from UI and using setter and getter we set to Hibernate entity and latter you will save that entity.
This question might help you.
DTO to Entity And Entity to DTO
When you are working with HTML(not with JSP), it better to use #RequestBody at place of #ModelAttribute to get complete body of data. Please refer the following links:
Link 1
Link 2

Resources