Django - How do I set default value to primary key - python-3.x

I have made custom User model with AbstractBaseUser.
and I'm trying to make the primary key of the class to start from certain numbers as new users sign up to the site.
Such as '2022001' - '2022002' - '2022003' and so on.
I have searched on stack overflow and other sources, and some people suggest define function within the custom user's class model, but i have failed to do that.
is there a simple way to generate auto_increment number starting with the custom number from models.py ?
or Is it possible for me to give that certain number in views.py as new users sign up?.
here is my register function. from views.py
def register_user(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
messages.success(request, ("You have successfully registered."))
return redirect('home')
else:
form = RegistrationForm()
return render(request, 'register/register_user.html', {'form' : form})
Thank you

user = authenticate(id=2022001 ,username=username, password=password)
if you want to modify your primary key this method may help.
try this.....

add following field to your model:
id = models.BigIntegerField(primary_key=True)
now you give it what ever value you'd like

Related

replacing token with a value

i am trying to replace token by checking whether the token is valid and then taking out the details using that token .
eg:
{"jwt":"asdahasjkaiubdkjsdjasdajkdjakdon","hostel":"BCJ bhawan","room_no":"300"......}
something like this i will receive
how can i replace that token portion with the value in serializer1
but i am unable to merge them together
here is my views.py
class leaveview(APIView):
def post(self,request):
token = request.data['jwt']
if not token:
raise AuthenticationFailed('Unauthenticated')
try:
payload = jwt.decode(token,'secret',algorithms=['HS256'])
except jwt.ExpiredSignatureError:
raise AuthenticationFailed('Unauthenticated')
user=User.objects.filter(id=payload['id']).first()
serializer1=UserSerializers(user)
serializer2 = leaveSerializers(data=request.data)
serializer2.is_valid(raise_exception=True)
serializer=serializer1+serializer2
serializer.save()
return Response(serializer.data)
models.py
class leave(models.Model):
name=models.CharField(max_length=100)
father_name=models.CharField(max_length=100,null=True)
branch=models.CharField(max_length=40,null=True)
coer_id=models.CharField(max_length=12,unique=True,null=True)
hostel = models.ForeignKey(hostel_manager,on_delete=models.CASCADE)
room_no = models.CharField(max_length=10)
where_to = models.CharField(max_length=100)
reason = models.CharField(max_length=300)
start_date = models.CharField(max_length = 100,null=True)
end_date = models.CharField(max_length=100,null=True)
phone_regex=RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+9999999999'. Up to 12 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=17)
serializer.py
class leaveSerializers(serializers.ModelSerializer):
class Meta:
model = leave
fields = ['id','hostel','room_no','where_to','reason','time_period','phone_number','name','father_name','branch','coer_id']
Two things first, you have two problems in your questions.
Firstly you want to replace a token with a value.
Secondly you want to merge serializer together.
In watching your code, we assume that you're using the jwt auth system from DRF.
Therefore you could simply use something as follow to retrieve the user and be sure that the user is authenticated :
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
...
class leaveview(APIView):
#permission_classes([IsAuthenticated])
def post(self,request):
...
user = request.user
...
Then you let DRF handling jwt auth without hussle.
For your merging issue, it's not a right idea to force uniting things from different nature in such way.
You would have to make serialize your data :
...
serializer1 = UserSerializers(user)
serializer1_data = UserSerializers(user).data
...
serializer2.is_valid(raise_exception=True)
merged_data = {**serializer1_data, **serializer2.data}
return Response(data=merged_data)
Above should be a working example, the ball is on your side to ease your code.

How to insert data to my DB when using another model's field in my form?

I have two different models: Trainer and User. I'm pulling in the trainer_price field from Trainer into my form in User. Please note that I'm also not using a foreign key.
The problem I'm having is that the trainer_price is not getting inserted and the default value of 0 is there, which is not what I want.
The way the User form works is they fill out their name, address, email and the trainer_price is automatically populated once they selected a trainer. It's also a read-only field.
Here's what I've tried so far:
user views.py
def buyer(request):
user_form = UserForm()
trainer_listing = Trainer.objects.get(id=15).trainer_price
context = {'user_form':user_form, 'trainer_listing':trainer_listing}
if request.method == "POST":
user_form = UserForm(request.POST)
if user_form.is_valid():
user_form.save()
return redirect("/success_page")
return render(request, "user/user_form.html", context)
forms.py
class UserForm(forms.ModelForm):
Fullname = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'John Doe'}))
Email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
Mobile = forms.CharField(widget=forms.TextInput(attrs={'placeholder': '312-222-2222'}))
Address = forms.CharField(widget=forms.TextInput(attrs={'placeholder': '1234 Main St'}))
City = forms.CharField()
State = forms.ChoiceField(choices=STATES)
zipcode = forms.CharField()
trainer_price = forms.DecimalField(label="Trainer Price", required=False, widget=forms.TextInput(attrs={'readonly':'readonly'}))
class Meta:
model = User
fields = ['Fullname','Email', 'Mobile', 'Address', 'City',
'State', 'zipcode', 'trainer_price']
Any help in the right direction would be great!
Basically, we can set default values for the form field using the initial argument.
def buyer(request):
trainer = Trainer.objects.get(id=15)
user_form = UserForm(initial={"trainer_price": trainer.trainer_price})
# etc
PS. Make sure that you do not populate the value from the trainer_price with the results from the request.POST. Smart users could use this to get very cheap deals. In stead, always re-query the actual value.

How to create new a new db entry only if certain values in the db do not already exist but some do?

I have a flask app that takes in user details and stores to PostgreSQL DB. The table in the DB has columns, email, location, and visits.
What I am trying to achieve:
If a user email is not in DB create new user entry.
If the user email exists and the location is the same, increment visits counter by 1.
If the user email exists but the location is different create new
user entry
Email is got through an HTML form and if passed on submit. Location is passed to the view via the URL(https://myapp.com/location.
Then end result will have duplicate email addresses in the DB if the user has visited different locations so can tell how many times that user has visited each location.
I have tried every possible way I can think all but all just create a new entry every time.
routes.py
if form.terms_and_conditions.data is not False:
if form.validate_on_submit():
customer = Client.query.filter_by
(email=form.email.data.lower()).first()
if customer is None:
full_client = Client(email=form.email.data.lower(),
location=location)
db.session.add(full_client)
db.session.commit()
return redirect(url_for('get_success'))
elif customer.location != location:
full_client = Client(email=form.email.data.lower(),
location=location)
db.session.add(full_client)
db.session.commit()
return redirect(url_for('get_success'))
elif customer.location == location:
customer.visits = customer.visits + 1
db.session.commit()
return redirect(url_for('get_success'))
else:
flash("Please enter a vaild E-mail address")
else:
flash("You must agree to the terms and conditions ")
return redirect(url_for('get_click', sitename=location))
models.py
class Client(db.Model):
client_id = db.Column(db.Integer, primary_key=True)
email = (db.Column(db.String(120), index=True, nullable=False))
location = db.Column(db.String(64), index=True)
visits = db.Column(db.Integer, default=1)
def __repr__(self):
return '{}>'.format(self.email)

Flask Sample webpage that request input from user performs no action

I trying to learn how to code in Flask and am building a small portal that accepts inputs from the user (User could select among various check boxes). Based on the input I am trying to display the selected columns by means of an excel file. Given below what I have done thus far and I am not sure how to take this forward.
#app.route('/index', methods=['GET','POST'])
def user_input():
form = SampleForm()
if form.validate_on_submit():
Username = form.username_field.data
Age = form.age_field.data
output = user_input(Username,Age)
return render_template('index', form=form)
I have managed to build the above code by reading through various blogs and posts but this does nothing. Could anyone guide me on where am I going wrong with the above sample piece of code. Thanks
Class.py
class test(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), nullable=False)
age = db.Column(db.String(100), nullable=False)
Python function:
def function(*field_names):
cursor = conn.cursor()
dwh_cursor.execute('select {} from enrolments'.format(', '.join(str(field) for field in field_names)))
print(field_names)
output_file = dwh_cursor.fetchall()
Does this help? Might need some tweaking to fit your needs.
#app.route('/index', methods=['GET','POST'])
def user_input():
form = SampleForm()
if form.validate_on_submit():
newform = User(
username = form.username_field.data,
age = form.age_field.data,
)
db.session.add(newform)
db.session.commit()
return redirect(url_for('user_input'))
return render_template('user_input', form = form)

how to restrict other user from updating an db object in Flask?

I am new to flask and building an ticket assigner application. Generator end point will assign always the oldest ticket(status=q) from the system to the person logged in. Then either he will resolve(post method = s) the ticket or can update its status to pending (post method = p).
#main.route('/ticket/generator', methods=['GET', 'POST'])
#login_required
def generate_ticket():
ticket = Ticket.query.filter_by(status='q').order_by(Ticket.create_date).first()
form = GenerateTicketForm(obj=ticket)
if form.validate_on_submit():
ticket.ticket_id = form.ticket_id.data
ticket.status = form.status.data
db.session.add(ticket)
db.session.commit()
flash('Ticket Status Update Successfully.')
return redirect(url_for('main.generate_ticket'))
return render_template('generate_ticket.html', form=form)
I want to change the status when the ticket already assigned to someone, so that other do not get the same ticket. So I have created a class method to change the status when getting the oldest ticket:
#classmethod
def activate_tkt_flag(cls, ticket_id_, create_date_):
ticket_db_obj = cls(ticket_id=ticket_id_, create_date=create_date_)
ticket_in_memory = Ticket.query.get(ticket_db_obj.ticket_id)
ticket_in_memory.status = 'a'
db.session.commit()
return ticket_in_memory
If call that after the ticket object in the first query it rewrite the loop some how and assign a new ticket and forget about the previous one the it can not rewrite the the ticket any more and I am getting that error: Key (ticket_id)=(T5) already exists UPDATE ticket SET ticket_id=%(ticket_id)s, status=%(status)s WHERE ticket.ticket_id = %(ticket_ticket_id)s'] [parameters: {'ticket_id': 'T5', 'status': 's', 'ticket_ticket_id': 'T1'}]. If some one has better idea how to do it will be grateful, I am kind of stuck here. Here is the form looks like.
Finally I was able to solve it. I just create one end point which execute first and update the ticket status and pass the ticket id to the next end point. So the last end point show the ticket with updated status to render template html.
#main.route('/ticket/generator/<ticket_id>', methods=['GET', 'POST'])
#login_required
def generate_ticket(ticket_id):
ticket = Ticket.query.get(ticket_id)
form = GenerateTicketForm(obj=ticket)
if form.validate_on_submit():
ticket.ticket_id = form.ticket_id.data
ticket.status = form.status.data
db.session.add(ticket)
db.session.commit()
# flash('Ticket Status Update Successfully.')
return redirect(url_for('main.display_status', ticket_id=ticket.ticket_id))
return render_template('generate_ticket.html', form=form)
#main.route('/ticket/assign')
def assign_ticket():
ticket = Ticket.query.filter_by(status='q').order_by(Ticket.create_date).first_or_404()
ticket.status = 'a'
db.session.commit()
return redirect(url_for('main.generate_ticket', ticket_id=ticket.ticket_id))
The assign end point execute first then the ticket id handed over to generator end point.

Resources