Adding None option to ModelChoiceFilter - django-filter

My filter has been working great but I'd like the option to select None to find Transactions where merchant_group==None. I can't find this option in the docs, is it not possible?
class TransactionFilter(django_filters.FilterSet):
merchant_group = django_filters.ModelChoiceFilter(field_name='merchant__merchant_group', empty_label="Merchant", queryset=MerchantGroup.objects.all().order_by('name'))

ModelChoiceFilter extends ChoiceFilter and passing a null_value (and a null_label optionally) can help you achieve this. Your code would look something like:
class TransactionFilter(django_filters.FilterSet):
merchant_group = django_filters.ModelChoiceFilter(
field_name='merchant__merchant_group', empty_label="Merchant", queryset=MerchantGroup.objects.all().order_by('name'), null_value=None, null_label='No merchant group'
)

Related

How to use keyTextTransform() for nested json?

My model has a json field. I can access jsonfield['key1'] with the following query
from django.contrib.postgres.fields.jsonb import KeyTextTransform
MyModel.objects.annotate(val=KeyTextTransform('key1', 'jsonfield')).order_by('val')
But how can I access a key like jsonfield['key1']['key2'] or even more nested ones?
This can't be the only solution, right?
MyModel.objects.annotate(val=KeyTextTransform('key2', (KeyTextTransform('key1', 'jsonfield'))).order_by('val')
The hard part is already done, thankfully. KeyTextTransform is composable. All we have to do is compose it.
class NestableKeyTextTransform:
def __new__(cls, field, *path):
if not path:
raise ValueError("Path must contain at least one key.")
head, *tail = path
field = KeyTextTransform(head, field)
for head in tail:
field = KeyTextTransform(head, field)
return field
MyModel.objects.annotate(
single_nested_value=NestableKeyTextTransform(
"json_field", "query", "name"
),
array_access=NestableKeyTextTransform(
"json_field", "query", "address_line", 1
),
)
Though I would like to point out that this may be a better way to do it:
from django.db.models import F
MyModel.objects.annotate(
single_nested_value=F("json_field__query__name"),
array_access=F("json_field__query__address_line__1"),
)
NB as of the start of 2023 (in django's development version) you can now also do:
from django.db.models.fields.json import KT
Dogs.objects.annotate(
first_breed=KT("data__breed__1"),
owner_name=KT("data__owner__name")
)
See docs and feature request

Access filter result Angular 6

How can I access filteredArray in my .ts component? Because right now it is accessible only inside ng-container.
<ng-container *ngIf="(userList | filter: 'name' : value) as filteredArray">
<tr *ngFor="let user of filteredArray">
<td>{{user.name}}</td>
<td>{{user.group}}</td>
</tr>
<div>Count: {{ filteredArray.length }}</div>
</ng-container>
How can I modify the code in order to obtain what I want? Thank you for your time!
To answer your question directly: it's not possible the way you describe it. But read on.
Pipes (sometimes still called "filters") should be used only to format data, i.e. prepare it in a human-readable form. For example, the build-in date pipe can be used to transform an ISO string to a string such as "March 21st, 1995", which is how a human from the USA might expect to read the date.
The way you're using pipes is not recommended, precisely because of the question you have. You've essentially put application logic inside a template, which is an anti-pattern and beats the purpose of having easy-to-read declarative templates, which Angular uses in order to figure out how to update DOM.
You should move the filtering logic back to the class. For example, instead of setting this.userList = xxx, you could have a function which you call every time, such as this.changeUserList(xxx).
changeUserList (list) {
this.userList = list
this.filteredArray = list.filter(...)
}
You can put this logic in a setter as well, which allows you to run custom code when you write the usual this.userList = list, but you'll need a separate (usually prefixed private) property on the class where you'd actually store the value. It's not really a limitation since you can also have a trivial getter, so you can still us this.userList normally as a getter without having to remember to use this._userList, essentially tucking this away as the get/set pair's implementation detail.
private _userList
public set userList (list) {
this._userList = list
this.filteredArray = list.filter(...)
}
public get userList (list) { return this._userList }
Observables could really come in handy here as well, since you could just rx.map the userList$ to filteredArray$ with an Array#filter.
public userList$
public filteredArray$ = this.userList$.pipe(map(arr => arr.filter(...))
Then in the template, you can use the async pipe.
*ngIf="filteredArray$ | async as filteredArray"
Avoid doing the following.... but it works for demo purposes 😃
Create a component (e.g. demo-element.component.ts) that takes a single #Input() value:any
Add this new component as the first child of the <ng-container>, and give it a template reference #containerRef e.g.:
<ng-container *ngIf="(userList | filter: 'name' : value) as filteredArray">
<demo-element #containerRef [value]="filteredArray"></demo-element>
In your main component, add
#ViewChild('containerRef') ref;
ngAfterViewInit() {
this.filteredArray = this.ref.value; // Terrible pattern, but answers the question:-)
}
I hope this below code will help you.
<div class="rsrvtn_blk" *ngIf="(items | fSearch:firstname) as filteredItems">
<div class="col-md-3 pl-0" *ngFor="let item of filteredItems">
// you can display the filtered content here
</div>
</div>

how to use [ngClass] for multiple class conditions Angular4

currently my div looks like this:
<div class="class-a" [ngClass]="{'class-b': !person.something}">
now I want to have another condition...
so now I want this div to be of class-a If something class-b If something else class-c
how should I do this?
im using angular 4.
thanks!
Add it like properties to an object literal:
[ngClass]="{'class-b': !person.something, 'other-condition': isOther }"
Another option is to return a string from the component if you think you need more complex logic, or know there will only be one. This might be more testable.
Whatever string you return will be rendered as a class(es)
[ngClass]="renderClass()"
renderClass() {
switch(this.user.theme){
case "dark":
return "dark-theme"
case "light":
return "light-theme"
}
}
The better way for use this Syntax ngStyle Because,
it's Not Completed Answer.
If you want to toggle some classes like text-info Or text-danger for <i> tag (
some exp ? 'text-info' : 'text-danger'
).
The best answer is array not object.
[ngClass] = "[some exp ? 'text-info' : 'text-danger', ...]"
GoodLuck

gocraft/dbr: How to JOIN with multiple conditions?

I develop web application with golang.
I use the library gocraft/dbr as O/R Mapper.
I have two tables: image and entry.
I join their tables and I want to get image_url.
type Image struct {
ImageUrl dbr.NullString `db:"image_url"`
}
type Entry struct {
CompanyImageID dbr.NullInt64 `db:"company_image_id"`
CompanyImage Image
EyecatchIamgeID dbr.NullInt64 `db:"eyecatch_image_id"`
EyecatchImage Image
}
Then I tried below:
var entry Entry
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), "entry.eyecatch_image_id = eyecatch_image.id").
LeftJoin(dbr.I("image").As("company_image"), "entry.company_image_id = company_image.id").
Load(&entry)
log.Println("company:", entry.CompanyImage)
log.Println("eyecatch:", entry.EyecatchImage)
result:
company: {{{https://company_image_url.png true}}}
eyecatch: {{{ false}}}
I expect below, but it did not become as expected.
company: {{{https://company_image_url.png true}}}
eyecatch: {{{{http://eyecatch_image_url.png true}}}
When I tried to change join condition like below:
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), "entry.eyecatch_image_id = eyecatch_image.id")
Load(&entry)
result:
company: {{{http://eyecatch_image_url.png true}}}
eyecatch: {{{ false}} {{ false}}}}
I don't know how to use join with multiple conditions.
Thank you.
The documentation is really poor - it seems they gave up on the idea of publishing the library. There is an open pull request that provides a little better documentation.. Here the author describes that you can create a multiple condition like this:
cond:= dbr.And(
dbr.Or(
dbr.Gt("created_at", "2015-09-10"),
dbr.Lte("created_at", "2015-09-11"),
),
dbr.Eq("title", "hello world"),
)
Then use the condition in any statement:
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), cond)
Load(&entry)

How can I groupBy and change content of the value in couchbase?

Exple :
I have a result like this
Result1 AFTER EMIT:
Key-------------------------------value
"2014/10/31" ----------------- {"A":a}
"2014/10/31" ----------------- {"B":b}
"2014/10/31"----------------- {"C":c}
"2014/10/31"----------------- {"D":d}
How can I output this new result from the previous one:
Key-------------------------value
"2014/10/31" -----------------{"Array":["A":a, "B":b, "C":c, "D":d]}
Is there a way? Any help will be appreciated. Thanks
You can use Couchbase v3 new N1QL query language for that. Also there is Query Language Tutorial. Specifically Array Comprehensions syntax.
I found it . Just do : group = true in the path or select it from the filter result .
and a reduce function to return all the values from the map. also you can add the start key = "2014/10/31" and end key= "2014/10/31".