Django: Creating a Reference Code for each new order - python

For my E-commerce project, I am trying to generate a reference code that can be understandable yet unique at the same time:
I am trying to generate a reference code that after each purchase is made that includes that day, month, year, hour, minute and a digit that increases with a new transaction
DDMMYYHHMMXXX
Day, Month, Year, Hour, Minute,3 digits starting with 001 and increasing with each new order.
How do I do it?
My current code generated is:
def create_ref_code():
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
model.py
class Order(models.Model):
ref_code = models.CharField(max_length=20, blank=True, null=True)
ordered_date = models.DateTimeField()
def __str__(self):
return self.user.username
This is how far I have reached but I am not sure how to increase the count with every new order
def create_ref_code():
now = datetime.now()
code = now.strftime("%y%m%d%H%M%S")
print(code)
count = + 1
digit = str(count).zfill(3)
my_code = (code, digit)
return ''.join(my_code)

for that you can extend the save method and retrieve all the order count and also you can use something like this to pad the leading zeroes on that count
str(1).zfill(3)
this will create 001 output in string and you need this in string format to concat the data so no need to convert that to integer again
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
count = ***retrieve you count of that orders using query*** + 1
digit = str(count).zfill(3)
self.reference_code = your logic to create reference code
updated:
you don't have to increment count like that
def create_ref_code():
now = datetime.now()
"""
'make query to count all todays order here'
count = Order.objects.filter(filter argument by date).count() + 1
"""
code = now.strftime("%y%m%d%H%M%S")
digit = str(count).zfill(3)
my_code = (code, digit)
return ''.join(my_code)

instead of DDMMYYHHMMXXX try UUID-4
code :
import uuid
uuid.uuid4()

Related

Python: Problem with passing prior function result and integer only dictionary into another function using database

#Database information I am pulling from for the first function that is working to calculate age:
from django.db import models
from datetime import date
class Patient_clients(models.Model):
pcfirstName = models.CharField('Client First Name', max_length=120)
pclastName = models.CharField('Client Last Name', max_length=120)
pcdob = models.DateField('Date of Birth', null=1/1/1900, blank=True)
#First function - it's working to calculate age from the information above.
#property
def calculateAge(self):
days_in_year = 365.2425
age = int((date.today() - self.pcdob).days / days_in_year)
return age
return self.calculateAge
#I am attempting to take the age and calculate the Life Expectancy from CDC tables I am providing in a dictionary. I have only fed the dictionary with a short data set to begin with to see if it works and when I set my patients up am setting their ages at a level that would populate a life expectancy in this data set. So far, no joy. I've tried multiple different variations of the return statement and have tried moving the dictionary under #property. I've also tried moving it into the function itself. I'm going to need to use the dictionary in other places eventually so felt it may be useful to make it global. I have a title populating the display but not the value. The keys represent the age, the values the life expectancy.
le = {'0':79, '1':78, '2':77, '3':76, '4':75, '5':74, '6':73, '7':72, '8':71, '9':70}
#property
def lifeEx(calculateAge, **dic):
for key, value in dic.items():
if calculateAge == key:
return le.value
I have also tried:
#property
def find_le(self):
dict = {'0':79, '1':78, '2':77, '3':76, '4':75, '5':74, '6':73, '7':72, '8':71, '9':70, '10':69, '11':68, '12':67, '13':66, '14':65, '15':65, '16':64, '17':63, '18':62, '19':61, '20':60, '21':59, '22':58}
days_in_year = 365.2425
age = int((date.today() - self.pcdob).days / days_in_year)
# return age
for key, value in dict.items():
if age == key:
return value
else:
return "Not found"

How to find one nearest date in HTML-Calendar django

i want to implement an event calendar. i am faced with the problem of displaying the closest event to today's date. to find the nearest date, i use __gte in queryset, after queryset finds all the nearest dates, I want to highlight the first one with a different color here is my solution could you tell me what i'm doing wrong?
This is my Model
class Events(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField()
start_time = models.DateTimeField()
end_time = models.DateTimeField()
def __str__(self):
return self.title
#property
def get_html_url(self):
url = reverse('cal:events', args=(self.slug,))
return f'<a href="{url}">'
And my HTMLCalendar
from datetime import datetime, timedelta
from calendar import HTMLCalendar
from .models import Events
class Calendar(HTMLCalendar):
def __init__(self, year=None, month=datetime.now().month):
self.year = year
self.month = month
super(Calendar, self).__init__()
# formats a day as a td
# filter events by day
def formatday(self, day, events):
events_per_day = events.filter(start_time__day=day)
d = ''
if Events.objects.filter(start_time__day=day, start_time__month=self.month).exists():
for event in events_per_day:
d += f'{event.get_html_url}'
if day != 0:
ev = Events.objects.filter(start_time__gt=datetime.now()).first()
if ev:
return f"<td>{d}<span style='color:red;' class='date'>{day}</span></a></td>"
else:
return f"<td>{d}<span style='color:aliceblue;' class='date'>{day}</span></a></td>"
return '<td></td>'
else:
if day != 0:
return f"<td><b><span class='date'>{day}</span> </b></td>"
return '<td></td>'
# formats a week as a tr
def formatweek(self, theweek, events):
week = ''
for d, weekday in theweek:
week += self.formatday(d, events)
return f'<tr> {week} </tr>'
# formats a month as a table
# filter events by year and month
def formatmonth(self, withyear=True, ):
events = Events.objects.filter(start_time__year=self.year, start_time__month=self.month)
cal = f'<table border="0" cellpadding="0" cellspacing="0" class="calendar">\n'
cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
cal += f'{self.formatweekheader()}\n'
for week in self.monthdays2calendar(self.year, self.month):
cal += f'{self.formatweek(week, events)}\n'
return cal
my solution is in the format day () function I am executing a query and if there is the first element I want to highlight it in red and paint over all the others with a different color
I'd consider moving the formatting to your template. You could then serve the first variable with the red formating and loop through the remaining values with the other formatting choice.
Use the view to generate the data you'll need in the template in the order you'd like to use it. Handle the presentation in the template.

Calculate a value from GraphQL and save it in Django models

I am trying to calculate a value from GraphQL. I am sending mutation to Django models but before save it I want to calculate this value with if statement (if the value is greater than 10 divide by 2, if is less than 10 multiply by 2).
I don't know where to add this function.
Here is my mutation in schema.py
class CreatePrice(graphene.Mutation):
price = graphene.Field(PriceType)
class Arguments:
price_data = PriceInput(required=True)
#staticmethod
def mutate(root, info, price_data):
price = Price.objects.create(**price_data)
return CreatePrice(price=price)
class Mutation(graphene.ObjectType):
create_product = CreateProduct.Field()
create_price = CreatePrice.Field()
schema = graphene.Schema(query = Query, mutation=Mutation)
And here is my Django model. Base price is calculated value and function name has two options(*2 or /2 it depends of initial value).
class Price(models.Model):
base_price = models.CharField(max_length = 20)
function_name = models.CharField(max_length = 20, choices = PROMO_FUNCTION)
def __str__(self):
return self.price_name
P.S. Sorry for bad English. Thanks!
I don't know why you are using CharField for base_price. So, I suggest you to do this:
#staticmethod
def mutate(root, info, price_data):
if int(price_data.base_price) >= 10:
price_data.base_price = str(int(price_data.base_price) / 2)
else:
price_data.base_price = str(int(price_data.base_price) * 2)
price = Price(base_price=price_data.base_price, function_name=price_data.function_name)
price.save()
return CreatePrice(price=price)
You can also create records in database by creating object and using save method on it.

How to make a function that calls aand prints each students name and courses

Here is what i have so far
from CSE_324_course import Course
from CSE_324_skeleton_student import Student
math = Course("Algebra I")
language = Course("Spanish I")
science = Course("Earth Science")
history = Course("U.S. History I")
phys_ed = Course("Physical Education I")
speaking = Course("Speech I")
art = Course("Art I")
test_student = Student("Jill", "Sample")
test_student.add_course(math)
test_student.add_course(language)
test_student.add_course(science)
test_student.add_course(history)
test_student2 = Student("Bill", "Sample")
test_student2.add_course(math)
test_student2.add_course(phys_ed)
test_student2.add_course(science)
test_student2.add_course(history)
test_student3 = Student("Kim", "Sample")
test_student3.add_course(language)
test_student3.add_course(speaking)
test_student3.add_course(science)
test_student3.add_course(art)
student_list=[test_student,test_student2,test_student3]
for (test_student,test_student2,test_student3 : get_course)
if (test_student().equals(search))
System.out.println(teststudnetgetCourse());
#Each iteration should:
#get,concatenate, and print the first and last name of the student
#print all courses for that student
#print a blank line between students
'''for this part you may need to review the other skeleton code to:
- see how to get items from a list
- see if there is code (like a function) in that file you can call in this file
- verify that running this file gets you the correct output with information from that file
Also, review syntax of pulling items from a list f
2 page of code
Course import Course
class Student:
student_id = 0
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
self.courses = []
self.student_id = Student.student_id
Student.student_id += 1
def __str__(self):
# TODO You will need to use a variable in the loop, so you must intialize it here,
# that variable will need to be initalized to get items listed in the first def _init_ section
# TODO add a loop that will go through the course list
# TODO Add code here to create a string representation of a student,
# including first and last name and all courses that student is taking
return "complete this return statement based on your in loop variable"
def get_first_name(self):
return self.first_name
def get_last_name(self):
return self.last_name
def get_student_id(self):
return self.student_id
def add_course(self, new_course):
# TODO add code to append new_course to self.courses
print "Course not yet added, implementation needed."
3rd page
class Course:
def __init__(self, course_name):
self.course_name = course_name
def __str__(self):
return self.course_name
I think you are looking to change
for (test_student,test_student2,test_student3 : get_course)
if (test_student().equals(search))
System.out.println(teststudnetgetCourse());
(which you have improperly indented) to:
for student in student_list:
print("{} {}".format(student.first_name, student.last_name))
for course in student.courses:
print(course) # This won't work because "2 page of code Course import Course" needs to be finished
print("\n") # blank line between students

Generate a Unique String in Python/Django

What I want is to generate a string(key) of size 5 for my users on my website. More like a BBM PIN.
The key will contain numbers and uppercase English letters:
AU1B7
Y56AX
M0K7A
How can I also be at rest about the uniqueness of the strings even if I generate them in millions?
In the most pythonic way possible, how can I do this?
My favourite is
import uuid
uuid.uuid4().hex[:6].upper()
If you using django you can set the unique constrain on this field in order to make sure it is unique. https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.unique
From 3.6 You can use secrets module to generate nice random strings.
https://docs.python.org/3/library/secrets.html#module-secrets
import secrets
print(secrets.token_hex(5))
A more secure and shorter way of doing is using Django's crypto module.
from django.utils.crypto import get_random_string
code = get_random_string(5)
get_random_string() function returns a securely generated random string, uses
secrets module under the hood.
You can also pass allowed_chars:
from django.utils.crypto import get_random_string
import string
code = get_random_string(5, allowed_chars=string.ascii_uppercase + string.digits)
Am not sure about any short cryptic ways, but it can be implemented using a simple straight forward function assuming that you save all the generated strings in a set:
import random
def generate(unique):
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
while True:
value = "".join(random.choice(chars) for _ in range(5))
if value not in unique:
unique.add(value)
break
unique = set()
for _ in range(10):
generate(unique)
If you can afford to lose '8' and '9' in the generated numbers there is a very pythonic solution to getting a random number.
import os
import base64
base64.b32encode(os.urandom(3))[:5].decode('utf-8')
Since you are going for uniqueness then you have a problem since 36 * 36 * 36 * 36 * 36 = 60'466'176 which will definitely result in collisions if you have millions. Since sets are faster than dicts we do...
some_set = set()
def generate():
return base64.b32encode(os.urandom(3))[:5].decode('utf-8')
def generate_unique():
string = generate()
while string in some_set:
string = generate()
some_set.add(string)
return string
However since uniqueness is usually more important I'd recommend generating a unique code for each of the numbers from 0 to 36^5 - 1 like this. We can use a large prime and modulo to make a psuedo-random number like this.
import base64
import math
num = 1
prime_number = 60466181
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789'
def num_to_code(n: int):
string = ''
hashed = hash_number(n)
for x in range(5):
charnumber = hashed % 36
hashed = math.floor(hashed / 36)
string += characters[charnumber]
return string
def hash_number(n: int, rounds = 20):
if rounds <= 0:
return n
hashed = (n * prime_number) % (36 ** 5)
return hash_number(hashed, rounds - 1)
if __name__ == '__main__':
code = num_to_code(1)
print(code)
Here are the results from generating 0-5, they'll always generate the same sequence.
0 AAAAA (easily fixable ofc)
1 ZGQR9
2 ON797
3 DUMQ6
4 31384
5 R8IP3
If you have a way of associating each user to a unique ID (for example Primary Key in Django or Flask). You can do something like this:
Note: This does not generate a fixed length.
We will pad the user_id to the right to make the generated length a bit static
import os
import base64
user_id = 1
#pad the string
number_generate = str(user_id).rjust(5,"0")
base64.b32encode(bytes(number_generate, 'utf-8')).decode('utf-8').replace('=','')
size = 5
''.join(random.choice(string.letters[26:] + string.digits) for in range(size))
this will generate some short code, but they can be duplicated. so check if they are unique in your database before saving.
def generate(size=5):
code = ''.join(random.choice(string.letters[26:] + string.digits) for in range(size))
if check_if_duplicate(code):
return generate(size=5)
return code
or using django unique constrain, and handle exceptions.
There is a function in django that does what you're looking for (credits to this answer):
Django provides the function get_random_string() which will satisfy
the alphanumeric string generation requirement. You don't need any
extra package because it's in the django.utils.crypto module.
>>> from django.utils.crypto import get_random_string
>>> unique_id = get_random_string(length=32)
>>> unique_id
u'rRXVe68NO7m3mHoBS488KdHaqQPD6Ofv'
You can also vary the set of characters with allowed_chars:
>>> short_genome = get_random_string(length=32, allowed_chars='ACTG')
>>> short_genome
u'CCCAAAAGTACGTCCGGCATTTGTCCACCCCT'
I have a unique field, named 'systemCode' within a lot of my models. And I am generating this manually, but also sometimes it can take value from user input, so I have to check this value before saving and if it matches , regenerating this value as a unique value.
And this is how I generate unique strings at this scenario :
This is my standard class Model :
class ClassOne(models.Model):
name = models.CharField(max_length=100)
systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
....
I am using save() method to generate and check this systemCode is unique :
def save(self, *args, **kwargs):
systemCode = self.systemCode
if not systemCode:
systemCode = uuid.uuid4().hex[:6].upper()
while ClassOne.objects.filter(systemCode=systemCode).exclude(pk=self.pk).exists():
systemCode = uuid.uuid4().hex[:6].upper()
self.systemCode = systemCode
super(ClassOne, self).save(*args, **kwargs)
But I have same systemCode field in all my Models. So I am using a function to generate value.
So, this is how to generate unique value for all models using saveSystemCode() function :
import uuid
def saveSystemCode(inClass, inCode, inPK, prefix):
systemCode = inCode
if not systemCode:
systemCode = uuid.uuid4().hex[:6].upper()
while inClass.objects.filter(systemCode=systemCode).exclude(pk=inPK).exists():
systemCode = uuid.uuid4().hex[:6].upper()
return systemCode
class ClassOne(models.Model):
name = models.CharField(max_length=100)
systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
....
def save(self, *args, **kwargs):
self.systemCode = saveSystemCode(ClassOne, self.systemCode, self.pk, 'one_')
super(ClassOne, self).save(*args, **kwargs)
class ClassTwo(models.Model):
name = models.CharField(max_length=100)
systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
....
def save(self, *args, **kwargs):
self.systemCode = saveSystemCode(ClassTwo, self.systemCode, self.pk, 'two_')
super(ClassTwo, self).save(*args, **kwargs)
class ClassThree(models.Model):
name = models.CharField(max_length=100)
systemCode = models.CharField(max_length=25, blank=True, null=True, unique=True)
....
def save(self, *args, **kwargs):
self.systemCode = saveSystemCode(ClassThree, self.systemCode, self.pk, 'three_')
super(ClassThree, self).save(*args, **kwargs)
while loop in the 'saveSystemCode' function is preventing to save same value again.
To generate unique one you can use below command:
import uuid
str(uuid.uuid1())[:5]
Here a solution to gen codes of lenght 5 or any on a file:
import shortuuid as su
n = int(input("# codes to gen: "))
l = int(input("code lenght: "))
shou = su.ShortUUID(alphabet="QWERTYUIOPASDFGHJKLZXCVBNM0123456789")
codes = set()
LEN_CNT = 0
with open('file.txt', 'w') as file:
while len(codes) < n:
cd = shou.random(length=l)
codes.add(cd)
if len(codes) > LEN_CNT:
LEN_CNT = len(codes)
file.write(f"{cd}\n")
(shortuuid sometimes gen duplicated codes, so I use a set to deal with that)
As the time of writing this answer, there is an actively maintained package that generates short UUIDs:
https://github.com/skorokithakis/shortuuid
For Django support, have a look here:
https://github.com/skorokithakis/shortuuid#django-field

Categories

Resources