django exedittabledataview search columns - django

I am trying to make a search option for my data table in my site,
in models.py I have:
class Mymodel(models.Model):
id = models.AutoField(primary_key=True)
title = models.TextField()
body = models.TextField()
creator = models.CharField(max_length=255, blank=True, db_index = True)
creation_time = models.DateTimeField( db_index = True )
event_id = models.CharField(unique=True, max_length=255)
capture_rule = models.ForeignKey(CaptureRule, db_index = True)
status = models.ForeignKey(EventStatus, null = True, blank=True, db_index = True)
comment = models.TextField( null = True, blank = True )
source_url = models.CharField(max_length=4096, null = True, blank = True )
links = models.ManyToManyField( Link, related_name = 'events' )
and in my views.py:
class edittest(XEditableDatatableView):
model = Event
template_name = 'webapp/index.html'
datatable_options = {
'columns':[( 'Time', 'creation_time', 'get_event_age' ),
( 'Status', 'status', make_xeditable( type='select' ), 'status__name' ),
( 'Creator', 'creator' ),
( 'Source', 'source' ),
( 'Title', 'title' ),
( 'Body', 'body', 'get_body_with_markup' ),
'comment',
'id',
'source_url',
( 'Tag', 'capture_rule__tag__name' ),
( 'Matcher', 'capture_rule__matcher'),
'linked_urls',
'capture_rule'
],
'search_fields': [ 'status__name' ],
'hidden_columns' : ['body', 'comment', 'id', 'source_url', 'linked_urls', 'capture_rule' ],
'ordering':['-creation_time'],
}
and it works ok but when I change the search_fields parameter to
'search_fields': [ 'title' ] or 'search_fields': [ 'comment' ]
it search in the whole columns like if I wrote : 'search_fields': []

That's probably because the search field should not already appear in the column list.
A list of filter-like ORM fields that are always appended to the list
of search fields when a search is performed on the table.
search_fields should only contain ORM paths to fields that aren't
already in the column definitions, since those are already searched by
default.
https://pypi.python.org/pypi/django-datatable-view/0.5.5

Related

Tagged union type including ManyToManyField and model constraints

Django ORM seems not to permit constraints on ManyToManyField.
class Component(ComponentMetaData):
class Type(models.IntegerChoices):
Part = 0
Components = 1
type = models.IntegerField(
choices=Type.choices,
)
components = models.ManyToManyField(
"self",
blank=True,
null=True,
)
def clean(self) -> None:
if self.type == 0 and self.components:
raise ValidationError("Parts could not have components.")
return super().clean()
class Meta:
constraints = [
models.CheckConstraint(
check=(
Q(type = 0) &
Q(components__isnull = True)
) | (
Q(type = 1)
# componenets only fields
),
name = "components_enum"
)
]
Migration attempt with the above model results in the error below;
ERRORS:
myapp.Component: (models.E013) 'constraints' refers to a ManyToManyField 'components', but ManyToManyFields are not permitted in 'constraints'.
Does anyone know why this is not permitted and what should one do if one would like to keep a ManyToManyField empty on some condition based on the values of other fields?
UPDATE 2023-01-24
Following the advise of #Selcuk, I tried below.
class Component(ComponentMetaData):
class TypeTag(models.IntegerChoices):
Part = 0
Components = 1
type_tag = models.IntegerField(
choices=TypeTag.choices,
)
child_components = models.ManyToManyField(
"self",
through="ComponentRelation",
blank=True,
null=True,
related_name="parent_component",
symmetrical=False,
)
def clean(self) -> None:
if self.type_tag == 0 and self.components:
raise ValidationError("Parts could not have components.")
return super().clean()
class Meta:
constraints = [
models.CheckConstraint(
check=(
Q(type_tag=0)
# part only fields
) | (
Q(type_tag=1)
# componenets only fields
),
name="component_enum"
)
]
class ComponentRelation(models.Model):
from_component = models.ForeignKey(
"Component",
on_delete=models.CASCADE,
related_name="from_component",
)
to_component = models.ForeignKey(
"component",
on_delete=models.CASCADE,
related_name="to_component",
)
class Meta:
constraints = [
models.CheckConstraint(
check=(
Q(from_component__type_tag = 1)
),
name="component_relation"
)
]
It results following error on migration.
myapp.ComponentRelation: (models.E041) 'constraints' refers to the joined field 'from_component__type_tag'.
It seems model constraint is a mere interface of DB functionality and could only include constraints for a single row, but no inter-table, complex constraints, generally speaking.
Is there any other way to do this??

Form attributes not displaying on webpage

I am trying to add classes to my forms but the classes are not being applied. I cannot find what I'm doing wrong. Any help would be greatly appreciated.
I'm hoping to set bootstrap classes, so I'd like , if possible.
class PersonalInformation(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200, default='')
surname = models.CharField(max_length=200, default='')
dob = models.DateTimeField('Date of birth (mm/dd/yyyy)', null=True, default=now)
preferred_subjects = models.CharField('Are there subjects you would prefer doing?', max_length=200, default='')
class PersonalInformationForm(forms.ModelForm):
OPTIONS = (
("ANI", "Animals"),
("ART", "Art"),
("COM", "Communication"),
)
preferred_subjects = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(
attrs={
'class' : 'not working',
'id' : 'not working'
}
), choices=OPTIONS)
class Meta:
model = PersonalInformation
fields = ['first_name', 'surname', 'dob', 'preferred_subjects']
widgets = {
'dob': DatePickerInput(
options={
"format": "MM/DD/YYYY",
"showClose": False,
"showClear": False,
"showTodayButton": False,
}
),
}
Thank you.
You can try Updating the form field attributes on initiallization.
class PersonalInformationForm(forms.ModelForm):
OPTIONS = (
("ANI", "Animals"),
("ART", "Art"),
("COM", "Communication"),
)
preferred_subjects = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(), choices=OPTIONS)
class Meta:
model = PersonalInformation
fields = ['first_name', 'surname', 'dob', 'preferred_subjects']
widgets = {
'dob': DatePickerInput(
options={
"format": "MM/DD/YYYY",
"showClose": False,
"showClear": False,
"showTodayButton": False,
}
),
}
def __init__(self, request, *args, **kwargs):
super(PersonalInformationForm, self).__init__(*args, **kwargs)
self.fields['preferred_subjects'].widget.attrs.update({'class': 'form-control', 'placeholder': 'First Name'})
EDIT:
preferred_subjects = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(), choices=OPTIONS)
preferred_subjects.widget.attrs.update({'class': 'form-control'})
class Meta:
model = PersonalInformation
fields = ['first_name', 'surname', 'dob', 'preferred_subjects']
widgets = {
'dob': DatePickerInput(
options={
"format": "MM/DD/YYYY",
"showClose": False,
"showClear": False,
"showTodayButton": False,
}
),
}
if this doesnt work, consider using 'SelectMultiple' instead of 'CheckboxSelectMultiple'
forms.MultipleChoiceField(widget=forms.SelectMultiple(), choices=OPTIONS)

Use of Prefetch with an inner select_related in Django

I basically have to display a list of service providers and in each, I need to display the categories of service they offer.
So as an example:
Possible Service Type Categories:
[id: 1, name:'Programming']
[id: 2, name:'Design']
Possible Service Types:
[id: 1, name: 'PHP Service', service_type_category_id: 1]
[id: 2, name: 'JAVA Service', service_type_category_id: 1]
[id: 3, name: 'Web Design Service', service_type_category_id: 2]
Example of Display Results:
Company Blue offers 'Programming'
Company Test offers 'Programming' and 'Design'
Company Orange offers 'Design' ....
I'm trying to write the least number of queries:
I have these models:
class ServiceTypeCategory( BaseModel ):
# Model Attributes
name = models.CharField( _( "name" ), max_length = 40 )
class ServiceType( BaseModel ):
# Model Attributes
service_type_category = models.ForeignKey( 'ServiceTypeCategory', verbose_name = _( 'category' ) )
name = models.CharField( _( "name" ), max_length = 60 )
description = models.TextField( _( "description" ) )
class Provider( BaseModel ):
# Model Attributes
display_name = models.CharField( _( "name" ), max_length = 80 )
# Many to many relations
countries = models.ManyToManyField( 'core.Country' ) # countries this provider support
service_types = models.ManyToManyField( 'ServiceType', through = 'Provider_ServiceTypes', related_name = 'service_types' )
class Provider_ServiceTypes( BaseModel ):
# Model Attributes
service_type = models.ForeignKey( 'ServiceType', verbose_name = _( 'service type' ) )
provider = models.ForeignKey( 'Provider', verbose_name = _( 'provider' ) )
is_top = models.BooleanField( _( "is top service" ), default = False )
Then, to run the query, I have the following:
providers = Provider.objects.select_related(
'user',
).prefetch_related(
Prefetch(
'service_types__service_type_category',
queryset = ServiceTypeCategory.objects
.only( 'name' )
)
).filter(
countries = country_id,
).only(
'id', 'display_name', 'user'
).order_by(
'-user__last_login'
)
This works out well, but it runs the 3 following queries:
SELECT app_provider.id, app_provider.user_id, app_provider.display_name, core_user.id, core_user.password, core_user.last_login, core_user.is_superuser, core_user.created_date, core_user.modified_date, core_user.email, core_user.name, core_user.is_active, core_user.is_admin
FROM app_provider
INNER JOIN app_provider_countries ON ( app_provider.id = app_provider_countries.provider_id )
INNER JOIN core_user ON ( app_provider.user_id = core_user.id )
LEFT OUTER JOIN core_userpersonal ON ( core_user.id = core_userpersonal.user_id )
LEFT OUTER JOIN core_userstats ON ( core_user.id = core_userstats.user_id )
WHERE app_provider_countries.country_id = 204
ORDER BY core_userstats.total_reviews DESC, core_userstats.total_contracts DESC, core_userstats.total_answers DESC, core_user.last_login DESC LIMIT 5
SELECT (app_provider_servicetypes.provider_id) AS _prefetch_related_val_provider_id, app_servicetype.id, app_servicetype.created_date, app_servicetype.modified_date, app_servicetype.service_type_category_id, app_servicetype.name, app_servicetype.description
FROM app_servicetype
INNER JOIN app_provider_servicetypes ON ( app_servicetype.id = app_provider_servicetypes.service_type_id )
WHERE app_provider_servicetypes.provider_id IN (2)
SELECT app_servicetypecategory.id, app_servicetypecategory.name
FROM app_servicetypecategory
WHERE app_servicetypecategory.id IN (1, 2)
Question is: How can I make to run just 2 queries in total? (The last 2 queries should be joined with INNER JOIN and a group by per service_type_category_name)
Thanks in advance!
Try this:
providers = Provider.objects.select_related(
'user',
).prefetch_related(
Prefetch(
'service_types',
queryset = ServiceType.objects\
.select_related('service_type_category')\
.only( 'service_type_category', 'name' )
)
).filter(
countries = country_id,
).only(
'id', 'display_name', 'user'
).order_by(
'-user__last_login'
)

list_filter triggering a FieldError

One of my queries suddenly started to fail after I made some changes to the AdminModel.
After searching a bit, I found that adding a list_filter to my admin_model is creating the FieldError, which seems really strange to me...
My models:
class PiafInfo( models.Model ):
no = models.IntegerField( u'No du Piaf', unique=True )
origin_city = models.ForeignKey( City )
...
class PiafInfoAdmin( admin.ModelAdmin ):
list_display = ('no', 'origin_city', 'group', 'fleet')
list_filter = ['origin_city', ]
ordering = ('no',)
search_fields = ('no', 'group', 'fleet')
admin.site.register( PiafInfo, PiafInfoAdmin )
class PiafTrans( models.Model ):
ttype = models.IntegerField( choices=TTYPE_CHOICES, default=TTYPE_RELOAD)
date = models.DateTimeField()
piafSerial = models.ForeignKey( PiafInfo )
...
class PiafTransAdmin( admin.ModelAdmin):
list_display = ('date', 'piafSerial', 'city', 'ttype', 'amount', 'subscrName' )
date_hierarchy = 'date'
list_filter = ('city', 'ttype')
search_fields = ('piafSerial', 'group', 'fleet', 'subscrName' )
admin.site.register( PiafTrans, PiafTransAdmin )
The query posing problem (second line) :
piafInfos = models.PiafInfo.objects.all().distinct()
piafInfos = piafInfos.filter( piaftrans__date__range=(startDate,endDate) ).distinct()
Like that, I get the following error:
FieldError: Cannot resolve keyword 'piaftrans' into field. Choices are: fleet, group, id, no, origin_city
It tries to interpret piaftrans as a field name instead of a model.
If I comment a single line in PiafInfoAdmin:
class PiafInfoAdmin( admin.ModelAdmin ):
list_display = ('no', 'origin_city', 'group', 'fleet')
# list_filter = ['origin_city', ]
ordering = ('no',)
search_fields = ('no', 'group', 'fleet')
admin.site.register( PiafInfo, PiafInfoAdmin )
The error disappears. I don't see any correlation between the error and the change I made!
This is with django 1.3 and Python 2.7 on Windows.
Can't reproduce here. Using
models.py:
class City( models.Model ):
name = models.CharField(max_length=110)
class PiafInfo( models.Model ):
no = models.IntegerField( u'No du Piaf', unique=True )
origin_city = models.ForeignKey( City )
class PiafTrans( models.Model ):
ttype = models.IntegerField()
date = models.DateTimeField()
piafSerial = models.ForeignKey( PiafInfo )
admin.py:
class PiafInfoAdmin( admin.ModelAdmin ):
list_display = ('no', 'origin_city',)
list_filter = ['origin_city', ]
ordering = ('no',)
search_fields = ('no',)
admin.site.register( PiafInfo, PiafInfoAdmin )
class PiafTransAdmin( admin.ModelAdmin):
list_display = ('date', 'piafSerial', 'ttype', )
date_hierarchy = 'date'
list_filter = ('ttype')
search_fields = ('piafSerial', )
admin.site.register( PiafTrans, PiafTransAdmin )
django 1.3.8 pre-alfa (latest from 1.3 branch)
and the following code:
startDate = datetime.today()
endDate = datetime.today()
piafInfos = PiafInfo.objects.all().distinct()
piafInfos = piafInfos.filter( piaftrans__date__range=(startDate,endDate) ).distinct()

pre populate Django AdminSplitDateTime()

I have a custom form as follows
class ticketform( BootstrapForm ):
class Meta:
layout = (
Fieldset( "", "project", "manager", "cc_to", "urgency", "deadline", "subject", "steps", "result", "desc", "file" ),
)
project = forms.CharField( max_length = 100, label = "Project", help_text = "Project this request is related to" )
manager = UserModelChoiceField( queryset = User.objects.filter( is_active = True ).order_by( 'first_name' ), label = "Manager",
help_text = "Immediate superior or project manager", required = True )
cc_to = UserMultipleSelectField( queryset = User.objects.filter( is_active = True ).order_by( 'first_name' ), label = "CC To",
widget = widgets.FilteredSelectMultiple( "Users", is_stacked = True ), required = False )
OPTIONS = (
( 'Critical', 'Critical' ),
( 'Major', 'Major' ),
( 'Minor', 'Minor' ),
)
urgency = forms.ChoiceField( choices = OPTIONS, label = "Urgency", help_text = "Urgency of the request" )
deadline = forms.CharField( widget = widgets.AdminSplitDateTime(), label = "Deadline",
help_text = "When should this ticket be completed", required = True )
subject = forms.CharField( max_length = 100, label = "Subject", help_text = "Ticket Subject" )
steps = forms.CharField( widget = forms.Textarea, label = "Steps", help_text = "Reproducible error/feature Steps" )
result = forms.CharField( widget = forms.Textarea, label = "Result", help_text = "Expected Result" )
desc = forms.CharField( widget = forms.Textarea, label = "Description", help_text = "Detailed Description" )
file = forms.FileField( label = "File", help_text = "Attach File Max size 10MB", required = False )
i have the following code in my view to populate the form for view
def view_ticket( request, ticket_id ):
ticket = Ticket.objects.filter( pk=ticket_id )[0]
dict = {'project' : ticket.project,
'manager' : ticket.manager.pk,
'urgencry': ticket.urgency,
'deadline': ticket.deadline,
'subject' : ticket.subject,
'steps' : ticket.steps,
'result' : ticket.result,
'desc' : ticket.detailed_disc,
'file' : ticket.attachments,
'cc_to' : ticket.cc_to.all()
}
form = ticketform( dict )
return render_to_response( 'form/request.html', {'form':form,
},
mimetype="text/html", context_instance=RequestContext( request ) )
now what is happening is that the deadline field is not being populated (all other fields gets populated just fine). all though i pass it the values in dictionary. Is there a way to pre-populated the AdminSplitDateTime() field on the form ?
setting the initial value for the form worked as pointed out by jpic