Add extra column to tables in django_tables2 - django

I want to add extra-column which is not in my model. And I apply one of the solutions at this site to my project. But it doesn't work properly.
model.py
class Companies(models.Model):
legal_name = models.CharField(max_length=120, blank=True)
co_name = models.CharField(max_length=120, blank=True)
client = models.ForeignKey(Clients, models.SET_NULL, blank=True, null=True)
tel_no = models.CharField(max_length=120, blank=True)
email = models.EmailField(null=True, blank=True)
address = models.TextField(null=True, blank=True)
contact = models.CharField(max_length=250, blank=True)
con_tel_no = models.CharField(max_length=120, blank=True)
entity = models.CharField(max_length=2, null=True)
yearend = models.DateField(null=True, blank=True)
bn = models.CharField(max_length=9)
memo = models.TextField(null=True, blank=True)
slug = models.SlugField(null=True, blank=True)
def t2_due_date(self):
now_year = datetime.date.today().year
if self.entity == 'CO':
yearend_ = DateWidget.decompress(self, self.yearend)
if yearend_[1] > 6:
yearend_[2] = now_year + 1
yearend_[1] -= 6
else:
yearend_[2] = now_year
yearend_[1] += 6
t2_due = DateWidget.compress(self, yearend_)
return t2_due
tables.py
class ScheduleTable(tables.Table):
due_date_col = tables.Column(accessor='t2_due_date', verbose_name='T2 Due Date')
class Meta:
attrs = {"class": "paleblue", "width":"100%"}
fields = ['client','legal_name', 'co_name', 'entity', 'yearend', 'due_date_col']
model = Companies
When I run this program 'due_date_col' is always blank. It seems that the function('t2_due_date) does not go through. Do you have any clue to clear this problem?

As far as I know accessor points to related objects, rather than model's properties, methods etc.
What you can try is to make use of Table.render_{column} as so:
class ScheduleTable(tables.Table):
def render_due_date_col(self, record):
return record.t2_due_date()
See djanog tables official doc for more info.

Related

Django: Filter on model column with Regex

I have phone numbers stored as (921) 414-1313 in the database and I want to run a search lookup on that field, but I don't want to force them to include (, ' ', ) or -.
I'm using Postgres and tried to work with SearchVector initially, however it ran into the same challenge (so for now, I'm doing it the old fashioned way).
I have a model definition that returns an "unformatted" number as 9214141313, but I can't figure out how to query against my custom definition inside of the model?
Ultimately, I want a customer to be able to type in 921414 and get the response for the matching record.
GitHub:
https://github.com/varlenthegray/wcadmin/blob/dev/main/views.py#L25
Model:
class JobSite(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
quickbooks_id = models.IntegerField(editable=False, null=True, blank=True)
name = models.CharField(max_length=200, null=True, blank=True)
first_name = models.CharField(max_length=200, null=True, blank=True)
last_name = models.CharField(max_length=200, null=True, blank=True)
print_on_check_name = models.CharField(max_length=200, null=True, blank=True)
address = models.CharField(max_length=200, null=True, blank=True)
address_2 = models.CharField(max_length=200, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
state = models.CharField(max_length=50, null=True, blank=True)
zip = models.CharField(max_length=20, null=True, blank=True)
phone_number = models.CharField(max_length=30, null=True, blank=True)
email = models.CharField(max_length=400, null=True, blank=True)
service_interval = models.IntegerField(default=12)
next_service_date = models.DateField(null=True, blank=True)
primary_technician = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
active = models.BooleanField(default=True)
access_code = models.CharField(max_length=10, null=True, blank=True)
bill_parent = models.BooleanField(default=False)
requires_supporting_technician = models.BooleanField(default=False)
service_scheduled = models.BooleanField(default=False)
disable_service = models.BooleanField(default=False)
qb_created_on = models.DateTimeField(null=True, blank=True)
def __str__(self):
return f'{self.name}'
def phone_digits_only(self):
return re.sub("[^0-9]", "", self.phone_number)
#property
def is_past_due(self):
ignore_after = timezone.localdate() - relativedelta(years=5)
# noinspection StrFormat
if self.next_service_date:
if ignore_after >= self.next_service_date:
return False
else:
return timezone.localdate() > self.next_service_date
else:
return False
#property
def is_due_soon(self):
ignore_after = timezone.localdate() - relativedelta(years=3)
if self.next_service_date and self.next_service_date >= ignore_after:
three_months_future = timezone.localdate() + relativedelta(months=2)
return three_months_future > self.next_service_date
else:
return False
Views.py
def search_system(request, search_term=False):
if search_term:
job_sites = JobSite.objects.filter(
Q(first_name__icontains=search_term) |
Q(last_name__icontains=search_term) |
Q(quickbooks_id__icontains=search_term) |
Q(email__icontains=search_term) |
Q(phone_number_digits=search_term)
)
else:
job_sites = JobSite.objects.all().prefetch_related('customer')
data = []
for job in job_sites:
if job.first_name and job.last_name:
name = job.first_name + ' ' + job.last_name
elif job.customer.company:
name = job.customer.company
else:
name = job.customer.first_name + ' ' + job.customer.last_name
this_job = {'value': name}
data.append(this_job)
return JsonResponse(data, safe=False)
The best solution IMHO is to use the library phonenumbers which is very cleaned and well maintained.
Then do a custom "phone_cleaned" field where you add the signals "create" and "update" for this model, and update phone_cleaned accordingly (using the library to clean the phone number). And use that phone_cleaned to do all your searches.

grepelli issue with autocomplete_search_fields

class DemoProvider(models.Model):
def __str__(self):
if self.MidName == None:
return u'%s, %s' % (self.LastName, self.FirstName)
else:
return u'%s, %s %s' % (self.LastName, self.FirstName, self.MidName)
PracticeName = models.ForeignKey('DemoPractice', on_delete=models.CASCADE)
FirstName = models.CharField(max_length=255, null=True, blank=True)
MidName = models.CharField(max_length=255, null=True, blank=True)
LastName = models.CharField(max_length=255, null=True, blank=True)
class Billing1500(models.Model):
Practice = models.ForeignKey('DemoPractice', on_delete=models.CASCADE)
Provider = models.ForeignKey('DemoProvider', on_delete=models.CASCADE)
PatiName = models.CharField(max_length=255, null=True, blank=True, help_text='Last Name, First Name')
PatiDOB = models.CharField(max_length=255, null=True, blank=True)
PatiSex = models.CharField(max_length=255, null=True, blank=True)
#staticmethod
def autocomplete_search_fields():
return ("Provider_icontains", )
#admin.register(Billing1500)
class Billing1500(admin.ModelAdmin):
raw_id_fields = ('Provider',)
autocomplete_lookup_fields = {
'fk': ['Provider'],
}
pass
i'm trying to have autocomplete search fields in my grapellie admin models, however im getting errors when trying to bind my foreignkeys to my grappelli function. i'm having the following issue
ERRORS:
?: (grappelli.E001) Model Core.billing1500 returned bad entries for autocomplete_search_fields: Provider_icontains
HINT: A QuerySet for {model} could not be constructed. Fix the autocomplete_search_fields on it to return valid lookups.
reading the docs it looks like what I have should be correct no?

business generated has to come based on dcr(daily call report)

I have DCR & SalesMIS model. I want to get the business generated count. And if count is it should return the business_genrated else saleMIS.amount
I wrote a method in DCR model i.e. get_business_generated(self) and apply filter on SaleMIS model. Then trying to get the count of business_generated
ERROR:D:\Projects\Python\Django\kingllp\venv\lib\site-packages\django\db\models\base.py", line 95, in new
"INSTALLED_APPS." % (module, name)
RuntimeError: Model class builtins.DCR doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
This is DCR model
class DCR(models.Model):
STATUSES = (
('1N', 'Need Analysis'),
('2P', 'Proposal Stage'),
('3C', 'Competitive Selling'),
('4D', 'Decision Stage'),
)
prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE, related_name='dcrs')
date = models.DateField(blank=True)
status = models.CharField(choices=STATUSES, max_length=2, default='1N')
discussion_points = models.CharField(max_length=2047, blank=True)
business_generated = models.IntegerField(default=0)
is_new_business = models.BooleanField(default=False)
def get_business_generated(self):
date = self.date
client = self.prospect
sale = SalesMIS.objects.filter(date=date,client = Prospect)
salecount = sale.count()
if salecount==0:
return DCR.business_generated
else:
return SalesMIS.amount
This is SaleMIS model
class SalesMIS(models.Model):
class Meta:
verbose_name_plural = _("Sale MIS")
date = models.DateField()
fls = models.ForeignKey(Employee, blank=True, null=True, on_delete=models.SET_NULL, related_name='sales')
amount = models.DecimalField(max_digits=20, decimal_places=2)
po_number = models.CharField(max_length=255, null=True, blank=True)
products = models.CharField(max_length=255, null=True, blank=True)
client = models.ForeignKey(Client, blank=True, null=True, on_delete=models.SET_NULL, related_name='client_mis')
def __str__(self):
return str(self.date) + ":" + self.fls.full_name()
Business share has to come based on DCR/MIS.

Error with Signals Post_Save and Pre_Save: created and self! how to fix?

It is necessary that after the addition of the series, the number of
the series is automatically added, if the administrator forgets to
add, in this way: we take the last created series, from there we take
the series number, and add to this the number of the series 1, and add
to our series! But constantly vylazyut such errors as:
1) lacks the
argument "self", add it (although why it is there at all, it is not
known) and still does not work!
this is my models and SIGNALS
class Series(models.Model):
id = models.AutoField(primary_key=True)
rus_name = models.CharField(max_length=60)
eng_name = models.CharField(max_length=60)
slug = models.SlugField(unique=False)
serial_of_this_series = models.ForeignKey(Serial, on_delete=models.CASCADE, default=True)
season_of_this_series = models.ForeignKey(Season, on_delete=models.CASCADE, default=True)
number_of_series = models.IntegerField(default=0, blank=True, null=True)
description = models.TextField(max_length=700, blank=True, default=None)
size_of_torent_file = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_360p = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_720p = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_1080p = models.CharField(max_length=60, default=None)
rating = models.FloatField(default=0, blank=True)
is_active = models.BooleanField(default=True)
timestamp_rus = models.DateField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
timestamp_eng = models.CharField(max_length=60)
time_of_series = models.DecimalField(max_digits=10, decimal_places=2, default=42)
def get_absolute_url(self):
return reverse('series:post_of_serie', kwargs=
{'serial_slug': self.serial_of_this_series.slug,
'season_slug': self.season_of_this_series.slug,
'series_slug': self.slug})
def __str__(self):
return "%s | %s" % (self.rus_name, self.number_of_series)
class Meta:
ordering = ["-timestamp_rus"]
verbose_name = 'Series'
verbose_name_plural = 'Series'
def series_change_number(sender, **kwargs):
ser = Series.objects.last()
change = ser.number_of_series
number = int(change) + 1
series = Series
series.number_of_series = number
series.save(force_update=True)
pre_save.connect(series_change_number, sender=Series)
ok do this:
def series_change_number(sender, instance, **kwargs):
ser = Series.objects.last()
change = ser.number_of_series
number = int(change) + 1
instance.number_of_series = number
pre_save.connect(series_change_number, sender=Series)
provided you are looking to update the new model object.
Please don't line up your code like that; it makes it very hard to read.
Your problem is here (removing the spaces):
series = Series
That just makes series another name for the Series class. You don't ever instantiate it; to do so you need to actually call it.
series = Series()
... assuming that is actually what you want to do; it's not clear from your code.

Using django modelform for 2 instances not saving correctly

In Django 1.6.1 I have a vehicle model which might zero or up to 2 traded-in units. Every time I edit any record, whether the change is trade-in instance #1 or instance 2, both records are updated with values instance #2.
Vehicle model:
class Vehicle(models.Model):
stock = models.CharField(max_length=10, blank=False, db_index=True)
vin = models.CharField(max_length=17, blank=False, db_index=True)
#vinlast8 = models.CharField(max_length=8, blank=False, db_index=True)
make = models.CharField(max_length=15, blank=False)
model = models.CharField(max_length=15, blank=False)
year = models.CharField(max_length=4, blank=False)
registry = models.IntegerField(blank=True, verbose_name='Reg #', null=True)
plate = models.CharField(blank=True, null=True, max_length=10)
tagno = models.IntegerField(blank=True, null=True, verbose_name='Tag #')
tag_exp = models.DateField(blank=True, null=True, verbose_name='Tag Exp')
Tradein model:
class TradeIn(Vehicle):
TradeInVehicle = (
(1, 'First vehicle'),
(2, 'Second vehicle'),
)
vehicle_sale = models.ForeignKey(VehicleSale)
tradeinpos = models.IntegerField(choices=TradeInVehicle)
lienholder = models.CharField(max_length=15, blank=True, null=True, verbose_name='L/holder')
lhdocrequested = models.DateField(blank=True, null=True, verbose_name='D/Requested')
lhdocreceived = models.DateField(blank=True, null=True, verbose_name='D/Received')
class Meta:
db_table = 'tradein'
def __unicode__(self):
return self.stock
def save(self, *args, **kwargs):
self.stock = self.stock.upper()
self.vin = self.vin.upper()
return super(TradeIn, self).save(*args, **kwargs)
The related sections on view is:
These sections are related to request.GET
current_vehicle = VehicleSale.objects.get(pk=pk)
tradeIns = current_vehicle.tradein_set.all().order_by('tradeinpos')
# Also add tradein_form to t_data so it can be rendered in the template
t_count = tradeIns.count()
if t_count == 0:
t_data['tradein1_form'] = TradeInForm()
t_data['tradein2_form'] = TradeInForm()
if t_count >= 1 and tradeIns[0] and tradeIns[0].tradeinpos == 1:
t_data['tradein1_form'] = TradeInForm(instance=tradeIns[0])
t_data['tradein2_form'] = TradeInForm()
if t_count == 2 and tradeIns[1] and tradeIns[1].tradeinpos == 2:
t_data['tradein2_form'] = TradeInForm(instance=tradeIns[1])
Now these are related to request.POST:
if 'tradein-form' in request.POST:
if tradeIns.count() > 0:
if tradeIns[0]:
tradein1_form = TradeInForm(request.POST, instance=tradeIns[0])
if tradein1_form.is_valid():
tradein1_form.save()
if tradeIns[1]:
tradein2_form = TradeInForm(request.POST, instance=tradeIns[1])
if tradein2_form.is_valid():
tradein2_form.save()
While reviewing contents of request.POST, it does contain any change I make in either instance. But always, the 2nd instance is saved.
What am I missing or have wrong?