How to auto increment unique number with a prefix? - django

How can I increment an invoice number with a prefix “INV” and number that increments ‘0001’, ‘0002’, ‘0003’......and so on..... when the user creates an invoice?
class Invoice(model.Models):
clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True,null=True)
invoice_number = invoice_number = models.CharField(max_length=200, blank=True, null=True)
Once the user creates/saves the invoice form, the hidden field(invoice field) should be auto-filled with invoice number
e.g.
client
invoice
client_name1
INV-001
client_name2
INV-002
client_name4
INV-003
client_name8
INV-004

You can make this process in save model method:
class Invoice(model.Models):
clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True,null=True)
invoice_number = models.CharField(max_length=200, blank=True, null=True)
def save(self):
if not self.invoice_number and self.pk is None:
last_invoice = Invoice.objects.all().order_by("-pk").first()
last_pk = 0
if last_invoice:
last_pk = last_invoice.pk
self.invoice_number = "INV-" + str(last_pk+1).zfill(3)
super(Invoice, self).save()
I am using the primary key for incremental number, but you can use another field in the model for making this task.

Related

Django modal autoimplement

Can anyone advise on how to deal with retrieving data from other models in Django? I was able to put information with the name of the company in the form, but after choosing from dropdown, I would like the tax identification number from database to be completed automatically. The problem is both the automatic completion and the binding and extraction of data.
p[1]: https://i.stack.imgur.com/V3TJ7.png
p[2]: https://i.stack.imgur.com/qZYAG.png
Model:
klient_lista = Klient.objects.all().values_list("nazwa_firmy", "nazwa_firmy")
class Faktura(models.Model):
numer = models.CharField(max_length=260, blank=False, null=False, unique=True)
klient = models.CharField(max_length=260, choices=klient_lista)
NIP = models.CharField(max_length=260)
kwota_netto = models.FloatField(blank=False, null=True)
VAT = models.FloatField(blank=False, null=True)
kwota_brutto = models.FloatField(blank=False, null=True)
views:
#login_required
def Faktury(request):
faktura = Faktura.objects.all()
faktura_Form = Faktura_Form(request.POST or None)
if faktura_Form.is_valid():
faktura_Form.save()
return redirect(Faktury)
return render(request, 'Faktury.html', {'form': Faktura_Form, 'faktura': faktura})
You don't need to store klient objects in a variable instead use foreign key to connect the two tables. I hope you refer to the "number" field by tax identification number and it is defined in klient model.
class Faktura(models.Model):
klient = models.ForeignKey(Klient,on_delete=models.CASCADE)
NIP = models.CharField(max_length=260)
kwota_netto = models.FloatField(blank=False, null=True)
VAT = models.FloatField(blank=False, null=True)
kwota_brutto = models.FloatField(blank=False, null=True)
To use client name include following in you client model
class Klient(models.Model):
...model fields
def __str__(self):
return self.name
replace name with the field which stores client name

Retrieve items from Many-to-Many relationship in Django query

Models.py
class SalesOrderItems(models.Model):
item = models.ForeignKey(MasterItems, on_delete=models.CASCADE)
item_quantity = models.IntegerField(default=0)
class SalesOrder(models.Model):
delivery_method_choice = (('Full-Truck Load', 'Full-Truck Load'), ('Part-Truck Load', 'Part-Truck Load'))
status_choices = (('On Hold', 'On Hold'),('Ready to Dispatch', 'Ready to Dispatch'),('Dispatched', 'Dispatched'))
owner = models.ForeignKey(Teacher, on_delete=models.CASCADE, related_name='so_owner')
client = models.ForeignKey(MasterClient, on_delete=models.CASCADE, related_name='so_client')
reference_no = models.CharField(max_length=500, blank=True, null=True)
date = models.DateField(default=datetime.date.today)
shipment_date = models.DateField(default=datetime.date.today)
delivery_method = models.CharField(max_length=500, default='Full-Truck Load', choices=delivery_method_choice)
items = models.ManyToManyField(SalesOrderItems, related_name='items_so', blank=True, null=True)
status = models.CharField(max_length=500, default='On Hold', choices=status_choices)
origin = models.CharField(max_length=255)
destination = models.CharField(max_length=255)
I want to retrieve the items of a particular sales order by django query
My attempt to get the items:
items = []
for i in sales_orders:
so = SalesOrder.objects.filter(pk=i)[0]
print("items",so.items)
Output:
items classroom.SalesOrderItems.None
How can I get the list of items in a particular SalesOrder ??
sales_orders = SalesOrder.objects.prefetch_related('items').filter(**sales_filter_here)
for sales_order in sales_orders:
for sales_order_item in sales_order.items.all():
print(sales_order_item)
this query will work for you
SalesOrder.objects.filter(id=1).values_list('items__item__item_name')
below is my simple Masteritems model
class MasterItems(models.Model):
item_name = models.CharField(max_length=50)
def __str__(self):
return self.item_name
by this way you will get every item name in queryset. this is my simple output
<QuerySet [('rice',), ('pepsi',), ('Computer',)]>

How to write and retrieve data from ManyToManyField inside overrided save() method?

I need to write any data to ManyToManyField via Model's form in the template, but i get an error like "... needs to have a value for field "id" before this many-to-many relationship can be used.". It shows when I try to use self.service("service" is my ManyToManyField) in my overrided save() method. I know that ManyToManyField is not basic field and it returns something like queryset, but how can i manipulate data inside save() method, because "self.service" doesn't work.
# models.py
class Appointments(models.Model):
name = models.CharField(max_length=200, db_index=True, verbose_name='Имя, фамилия')
tel = models.CharField(max_length=200, db_index=True, verbose_name='Номер телефона')
e_mail = models.CharField(max_length=200, blank=True, db_index=True, verbose_name='E-mail')
car = models.ForeignKey('Cars', null=True, on_delete=models.PROTECT, verbose_name='Тип автомобиля')
num_car = models.CharField(max_length=200, null=True, db_index=True, verbose_name='Гос.номер автомобиля')
**service = models.ManyToManyField(Services, verbose_name='Тип услуги')**
date_created = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата публикации заявки')
date_service = models.DateField(db_index=True, verbose_name='Дата')
time_service = models.TimeField(db_index=True, help_text="Введите время в таком формате: 15:00", verbose_name='Время')
price = models.CharField(max_length=50, db_index=True, null=True, verbose_name='Цена')
def save(self, *args, **kwargs):
for i in Services_prices.objects.all():
ccar = i.car
sservice = i.service
for d in self.service:
if self.car == ccar and d == sservice:
self.price = i.price
break
elif ccar == None and d == sservice:
self.price = i.price
break
super().save(*args, **kwargs)
# forms.py
class AppointmentForm(forms.ModelForm):
service = forms.ModelMultipleChoiceField(queryset=Services.objects.all(), required=False, widget=forms.CheckboxSelectMultiple())
class Meta:
model = Appointments
fields = ('name', 'tel', 'e_mail', 'car', 'num_car', 'service', 'date_service', 'time_service')
In order to have a many_to_many relation between two objects, you need primary keys of the both objects. Before calling super's save, your model does not have a primary key yet.
In your overriden save method, call super first, (e.g.super().save(*args, **kwargs)) then do your stuff, then save again.

Django computed column with lookup from same table and if class

I am new to programming. I am trying to create a project management site. I created a model as follows:
class Boqmodel(models.Model):
code = models.IntegerField(unique=True)
building = models.ForeignKey(building, on_delete=models.SET_NULL, null=True)
level = models.ForeignKey(level, on_delete=models.SET_NULL, null=True)
activity = models.ForeignKey(activity, on_delete=models.SET_NULL, null=True)
subactivity = models.ForeignKey(sub_activity, on_delete=models.SET_NULL, null=True)
duration = models.IntegerField()
linkactivity = models.IntegerFeild(null=True) #contains code (same as code field) which this specific code is linked to
linktype = models.CharField(max_length=300, null=True)# only two choices start or finish
linkduration = models.IntegerField(null=True)
plannedstart = models.DateField()
plannedfinish = models.DateField()
The problem is I need my planned start as a computed column. The planned column should be as follows:
if linkactivity is null, then it should take a default value 01-01-2019
if else then it should look the linkactivity in code field and then
if linktype is start, then it should specify the start date of code activity +duration
or if linktype is finish plannedfinish + duration
Example
First entry:
code=1
building=A-1
Level=L-1
Activity=Activity-1
Subactivity-Subactivity-1
duration=2
linkactivity=null
linktype=null
linkduration=null
planned start=01-01-2019(as linkactivity=null)
plannedfinish=03-01-2019(planned start+duration)
Second entry:
code=2
building=A-1
Level=L-1
Activity=Activity-2
Subactivity-Subactivity-2
duration=3
linkactivity=1
linktype=start
linkduration=1
planned start=02-01-2019(as linkactivity=1,it searches code1 ,as linktype=start,it searches startdate of code 1 it is 01-01-2019 ; finally 01-01-2019+link duration(1)=02-01-2019)
plannedfinish=05-01-2019(planned start+duration)
Any help would be really appreciated
When you call Model.objects.create() method, the django ORM implicitly calls the Model.save() method inside your model. Since, you are inheriting BoqModel from models.Model and there is no explicit BoqModel.save() method in your BoqModel, Model.objects.create() method calls the save() method from the parent class. Inside Model.save() method you can customize your model save behavior. In order to achieve your intended action, override the save() method as follows -
class Boqmodel(models.Model):
code = models.IntegerField()
building = models.ForeignKey(building, on_delete=models.SET_NULL, null=True)
level = models.ForeignKey(level, on_delete=models.SET_NULL, null=True)
activity = models.ForeignKey(activity, on_delete=models.SET_NULL, null=True)
subactivity = models.ForeignKey(sub_activity, on_delete=models.SET_NULL, null=True)
duration = models.IntegerField()
linkactivity = models.IntegerFeild(null=True) #contains code (same as code field) which this specific code is linked to
linktype = models.CharField(max_length=300, null=True)# only two choices start or finish
linkduration = models.IntegerField(null=True)
plannedstart = models.DateField()
plannedfinish = models.DateField()
def save(self, *args, **kwargs):
if self.linkactivity is None:
self.plannedstart = datetime.date(year=2019, month=1, day=1)
else:
boq = BoqModel.objects.get(code=self.linkactivity)
if self.linktype is not None:
if self.linktype == "start":
self.plannedstart = boq.plannedstart + datetime.timedelta(days=self.linkduration)
elif self.linktype == "finish":
self.plannedstart = boq.plannedfinish + datetime.timdelta(days=self.linkduration)
else:
self.plannedstart = datetime.date(year=2019, month=1, day=1)
else:
self.plannedstart = datetime.date(year=2019, month=1, day=1)
self.plannedfinish = self.plannedstart + datetime.tiemdelta(days=self.linkduration)
super(BoqModel, self).save(*args, **kwargs)
The above is not optimized. But you get the general idea of how to do it. Also learn more about overriding predefined model methdos here.

Django populate select field based on model query

I have the following model
class DNS(models.Model):
domain = models.ForeignKey(Domain)
host_start = models.CharField(max_length=150, blank=True, null=True)
type = models.SmallIntegerField(max_length=1, default=0, choices=DNS_CHOICE)
value = models.SmallIntegerField(max_length=3, default=0, blank=True, null=True)
ip = models.IPAddressField(blank=True, null=True)
host_end = models.ForeignKey("DNS", blank=True, null=True)
other_end = HostnameField(max_length=150, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
sticky = models.BooleanField(default=0)
other = models.BooleanField(default=0)
When I try to init a form with just foreignkeys on host_end.. it always shows all entries in the DNS table
domain = Domain.objects.get(id=request.GET['domain'], user=request.user, active=1)
form = DNSFormCNAME(initial={'ip': settings.MAIN_IP, 'type': request.GET['type'], 'host_end': DNS.objects.filter(domain=domain)})
I just want the zones that match that domain.. not all domains.
Initial data to a choice or foreign key field is used to determine what is selected in that field, not what the available options are. If you want to determine the list of options, you need to override the form's __init__ method and do it there.
class DNSFormCNAME(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.domain = kwargs.pop('domain', None)
super(DNSFormCNAME, self).__init__(*args, **kwargs)
if self.domain:
self.fields['host_end'].queryset = DNS.objects.filter(domain=domain)