Saving a user specific data in django - python

I am currently working on my maiden django project where an authorised person can save their daily expenses. I have created the login and signup page using UserCeationForm and AuthenticationForm. My code for the same is:
def login_view(request):
if request.method == 'POST':
form= AuthenticationForm(data=request.POST)
if form.is_valid():
user=form.get_user()
login(request,user)
return render (request, 'tasks_notes/index.html')
else:
form= AuthenticationForm()
return render(request, 'registeration/login.html', {'form':form})
def signup_view(request):
if request.method == 'POST':
form= UserCreationForm(request.POST)
if form.is_valid():
user=form.save()
login(request,user)
return redirect('login')
else:
form=UserCreationForm()
return render(request, 'tasks_notes/signup.html',{'form':form})
I have created a page named index.html where I am giving input to save my daily expenses wfor the appropriate (logged in) user as:
<form class="col s12" action='{% url "add item" %}' method='post'>
{% csrf_token %}
<div class="row">
<div class="container center">
<h3 class='center'>Your total budget is: <span style="color:green;">{{ budget }}</span> dollars</h3>
<h3 class='center'>You've spent a total of: <span style="color:red;">{{ expenses }}</span> dollars</h3>
<br>
<br>
<div class="input-field col s3">
<input placeholder="Expense name" name="expense_name" id='expense_name' type='text' class='validate'>
<label for='expense_name'>Expense name</label>
</div>
<div class="input-field col s3">
<input placeholder='Amount' name='cost' id='cost' type='text' class='validate'>
<label for='cost'>Amount</label>
</div>
<div class="input-field col s3">
<input placeholder='Date of Expense' name="expense_date" id="expense_date" type="text" class='datepicker'>
<label for="expense_date">Expense Date</label>
</div>
<button class="btn waves-effect waves-light" type="submit" name="action">Add Expense
<i class="material-icons right">add_circle</i>
</button>
</div>
</div>
</form>
I am trying to take the inputs and put that in views.py file as:
def additem_view(request):
name = request.POST['expense_name']
expense_cost = request.POST['cost']
expense_date = request.POST['expense_date']
create=BudgetInfo.objects.create(items=name,cost=expense_cost,date_added=expense_date)
create.save()
return HttpResponseRedirect('app')
My models.py file is:
from django.db import models
from django.contrib.auth.models import User
class BudgetInfo(models.Model):
items= models.CharField(max_length=20)
cost= models.FloatField(blank=False, null=True)
date_added= models.DateField(auto_now=True)
user= models.ForeignKey(User, on_delete= models.CASCADE)
When I am giving the input in my web page, I am getting an error like this:
Exception Type: IntegrityError
Exception Value: NOT NULL constraint failed: tasks_notes_budgetinfo.user_id
I have checked for budgetinfo.user_id in my dbsqlite database I found this:
CREATE TABLE IF NOT EXISTS "tasks_notes_budgetinfo" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "items" varchar(20) NOT NULL, "cost" real NULL, "date_added" date NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
Sorry for such long explanation of my question. Can anyone tell me where am I wrong? It will be a great help.
Thank you.

try this
<form class="col s12" action='{% url "add item" %}' method='post'>
{% csrf_token %}
<input type="text" name="id" value="{{user.id}}">
</form>
and in your views
def additem_view(request):
name = request.POST['expense_name']
expense_cost = request.POST['cost']
expense_date = request.POST['expense_date']
id= request.POST['id']
create=BudgetInfo.objects.create(id=id,items=name,cost=expense_cost,date_added=expense_date)
create.save()
return HttpResponseRedirect('app')

Your BudgetInfo model has a ForeignKey pointing to the your User model. When saving the BudgetInfo you never made the link to the (non-null) user.
If you want the script to refer to the "current user" (the user who actually made the request after logging in) you should simply use request.user:
BudgetInfo.objects.create(
user=request.user,
items=name,
cost=expense_cost,
date_added=expense_date,
)
If you're linking this to "some other user", you'll need to find that user first then link it the same way:
BudgetInfo.objects.create(
user=User.objects.get(username="smassey"), # for example
items=name,
cost=expense_cost,
date_added=expense_date,
)

Related

I am trying to save the form data. My Django form data is not saved, why?

I am trying to save form data from Django template to Django Model. Its not throwing any error but its not saving the data as well
Could you please let me know what could be the problem and how should I solve?
Here is my Django form template:
<form method="POST" class="review-form" autocomplete="on">
{% csrf_token %}
<div class="rating-form">
<label for="rating">Your Overall Rating Of This Product :</label>
<span class="rating-stars">
<a class="star-1" href="#">1</a>
<a class="star-2" href="#">2</a>
<a class="star-3" href="#">3</a>
</span>
<select name="rating" id="rating" required=""
style="display: none;">
<option value="">Rate…</option>
<option value="3">Average</option>
<option value="2">Not that bad</option>
<option value="1">Very poor</option>
</select>
</div>
<textarea cols="30" rows="6"
placeholder="What did you like or dislike? What did you use this product for?" class="form-control"
id="review" name="description"></textarea>
<div class="row gutter-md">
<div class="col-md-12">
<input type="text" class="form-control"
placeholder="Your Name - This is how you'll appear to other customers*" id="author" name ="name">
</div>
</div>
<button type="submit" class="btn btn-dark">Submit Review</button>
</form>
My Forms.py
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = ('rating', 'description', 'display_name')
My Views:
def reviews(request, slug):
if request.method == "POST":
if request.user.is_authenticated:
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = Products.objects.get(slug=slug)
review.user = request.user
review.display_name = request.name
review.description = request.description
review.rating = request.rating
print(review)
review.save()
messages.success(request, "Review saved, Thank you for the feedback.")
return redirect('products:products')
else:
messages.error(request, 'Sorry! Only customer purchased this Item are eligible for the review')
else:
pass
return redirect('ecommerce:products')
Try using generic ClassBasedViews. It's worth it to learn the concept! You will have to write less code and you will be able to edit a model instance and delete it from the front end.

IntegrityError at /update/70 NOT NULL constraint failed: tohome_task.title

I was updating the data in the database by takin the data from an html form when this appeared. I have faced this problem earlier also but I dont remember how to solve it .
my views.py part
def update(request,pk):
task = Task.objects.get(id=pk)
context = {
'task':task,
}
if request.method=="POST":
task.title= request.POST.get('taskname' )
task.save()
return redirect('/main')
return render(request,"update.html",context)
models.py file :
class Task(models.Model):
title = models.CharField(max_length =200)
complete = models.BooleanField(default = False , blank=True)
created = models.DateTimeField(auto_now=True)
my html file :
<div class="container">
<div class="jumbotron mt-3">
<form method= "post">
{% csrf_token %}
<h1 class="text-center">{{task}}</h1>
<input type="text" class="form-control rounded " id="task_name" name="task_name"
aria-describedby="emailHelp" placeholder="Add the task !">
<p class="lead text-center" > Do you really want to update ?</p>
<button class="btn btn-lg btn-primary" type ="submit" >Update »</button>
</form>
</div>
</div>
Your html input element's name attribute does not match the key you are attempting to access in request.POST. You would need to update your name attribute on your input to name="taskname" as opposed to name="task_name"
I would also suggest taking a look at Django's form docs and possibly adding validation since your error was caused by attempting to update the Task.title field with a None value

Implementing select2 in form to query existing users, ModelMultipleChoiceField is always invalid on form

I inherited a project where we wanted to use django's native User model but also give users some additional fields. So I made a model called UserProfiles, which has a foreignkey to each User instance. I made a template to update these UserProfiles called settings-userprofile.html. Previously, we only had the field api_key for people to modify, so things were basic.
We want every User to have their own list of "assistant" Users, a label relevant for an API we'll be implementing. So I added the field assistants and updated settings-userprofile.html to include a <select multiple> element that lists out all the existing users on our site. We're using a theme/template that is able to implement the select2 pillbox/tokenization element (like the rightmost screencap in this picture)
user_profile/models.py
class UserProfile(models.Model):
phone_number = models.CharField(max_length=15, verbose_name='Phone Number')
user = models.OneToOneField(User, on_delete = models.CASCADE)
api_key = models.CharField(max_length=200, default='12345678',)
assistants = models.ManyToManyField(User, related_name="assistants")
settings-userprofile.html
<form class='form-horizontal' method="post" action="{% url 'profileUpdate' %}">
{% csrf_token %}
<div class="form-group row mb-4">
<label for="api_key" class="col-sm-3 col-form-label"><b>Profile Api Key:</b></label>
<div class="col-sm-9">
<input type="text" name="api_key" class="form-control" id="horizontal-apikey-input" value="{{ request.user.userprofile.api_key }}">
</div>
</div>
<div class="form-group">
<label class="control-label">User list</label>
<select name="assistants" class="select2 form-control select2-multiple" multiple="multiple" data-placeholder="Choose ...">
<optgroup label="Existing users">
{% for u in allUsers %}
{% if u in request.user.userprofile.assistants %}
<option selected value="{{ u.username }}">{{ u.username }}</option>
{% else %}
<option value="{{ u.username }}">{{ u.username }}</option>
{% endif %}
{% endfor %}
</optgroup>
</select>
</div>
<div class="form-group row justify-content-end">
<div class="col-sm-9">
<div>
<button type="submit" name='apikey_submit' class="btn btn-primary w-md">Submit</button>
</div>
</div>
</div>
</form>
user_profile/views.py
from .forms import UserProfileForm
#login_required
def display_settings_page(request):
form = UserProfileForm(instance=request.user)
allUsers = User.objects.all()
return render(request, 'settings-userprofile.html', { 'form':form, 'allUsers':allUsers })
#login_required
def settings_update_profile(request):
allUsers = User.objects.all()
if request.method == 'POST':
old_api = request.user.userprofile.api_key
form = UserProfileForm(data=request.POST, instance=request.user.userprofile)
if form.is_valid():
form.save()
messages.success(request, "Your API key was changed from " + old_api + " to " + form.cleaned_data["api_key"])
return render(request, 'settings-userprofile.html', {'form': form, 'allUsers':allUsers})
else:
print(form.errors)
return render(request, 'settings-userprofile.html', {'form': form, 'allUsers':allUsers})
# omitting the rest of this code since it only applies to GET requests
In forms.py, we represented assistants using forms.ModelMultipleChoiceField and specified the queryset as the set of all Users.
user_profile/forms.py
class UserProfileForm(forms.ModelForm):
api_key = forms.CharField(required=False)
assistants = forms.ModelMultipleChoiceField(required=False,
queryset=User.objects.all(),
)
class Meta:
model = UserProfile
fields = ['api_key', 'assistants']
This got me as far as to a point where I see a dropdown menu that lists out all the users on my site, and I can select 1 or more users. usernames and emails are the same on this application, so I see a list of emails as intended.
In the view function, I can use print(request.POST.getlist('assistants')) and it prints a list of the tokenized usernames selected in the dropdown menu on submission.
However, is_valid() is always failing and I'm not sure how to go about fixing it. For instance, we have a user registered at the email/username devtest4#gmail.com . Selecting them and Printing form.errors reveals...
<ul class="errorlist">
<li>assistants
<ul class="errorlist"><li>“devtest4#gmail.co
m” is not a valid value.</li></ul>
</li>
</ul>
The username still isn't being treated as a valid value, despite the fact that the queryset is specified to be a list of all users.

AbstractUser Login View

I've spent a couple of days on this, read the docs, read some Two Scoops info, and I'm missing something. I'm trying to make a view to log in an AbstractUser. The AbstractUser model is in my_app and the view is in an app called mainsite, that I use to store project-wide views.
After the user logs in, they will have access to class-based views that they will use to add, edit, and delete database records. These users are not staff, so I am not giving them access to the admin.
Every time I try to log in as a user, authenticate(username, password) (in views.py) returns none.
What am I missing?
Here's the setup--I have a custom Person model that extends the AbstractUser model:
# my_app.models.py
class Person(AbstractUser):
date_left = models.DateField(blank=True, null=True)
phone_number = models.IntegerField(blank=True, null=True)
def _full_name(self):
return self.get_full_name()
full_name = property(_full_name)
def __str__(self):
return self.get_full_name()
class Meta:
verbose_name_plural = 'People'
I've added Person to settings.py:
# settings.py
...
AUTH_USER_MODEL = "my_app.Person"
...
I have the following URLconf:
# project/urls.py
from mainsite.views import login_view
...
url(r'^login/$', login_view, name='login'),
...
This view logs in the user:
# mainsite.views.py
def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return render(request, 'logged_in.html')
else:
return render(request, 'login.html',
{'message': 'Bad username or password'}
)
else:
return render(request, 'login.html')
And finally, here's the template with the login fields:
#templates/login.html
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<div class="row column"><h1>Login</h1></div>
{% if message %}
<div class="row">
<div class="small-12 medium-6 columns">
<div class="alert callout">
<p>{{ message }}</p>
</div>
</div>
</div>
{% endif %}
<div class="row">
<div class="small-12 medium-6 columns">
<label>Username
<input type="text" id="username" name="username">
</label>
</div>
</div>
<div class="row">
<div class="small-12 medium-6 columns">
<label>Password
<input type="password" id="password" name="password">
</label>
</div>
</div>
<div class="row">
<div class="small-12 medium-6 columns">
<input type="submit" value="Log in" class="button">
</div>
</div>
</form>
I found an answer (with help from reddit) in the docs.
When you use AbstractUser, you need to create your own UserCreationForm and UserChangeForm. If you use AbstractBaseUser, then you will need to create additional forms.
I had not created these forms, and I created my users in the admin using forms automatically generated by Django. These forms did not set the password correctly. The automatically generated form probably used user.password = 'some_password'. The correct way to do it is user.set_password('some_password') .

How to encrypt plain text to md5 / sha1 in django?

i want to create an application that admin can make user with a new messages that encrypted into database. I have the core function and all can work properly. But, i still can't encrypt the message from text to md5/sha1. I have read and try this and this. But, i still can't do it. I'm new in django, and I'm very grateful for your response. Thank you
This is my models:
class UserProfile(models.Model):
user = models.OneToOneField(User) #digunakan untuk relasi ke model User (default) alias UserProfile adalah sebagai extending model
CATEGORY_CHOICES = (
('admin','Admin'),
('user','User'),
)
hak_akses = models.CharField(max_length=100, choices = CATEGORY_CHOICES)
messages = models.CharField(max_length=100, blank=True)
# password_pckelas = models.CharField(max_length=100, blank=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
This is my view function:
def tambah_user(request, template_name='form_user.html'):
#cek session
if 'username' in request.session and request.session['hak_akses'] == 'admin':
#ambil dari database untuk mengaktifkan ubah_password_admin
users = User.objects.all()
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
messages = profile_form.data['messages'] #ambil messages
if request.method == 'POST':
if user_form.is_valid() and profile_form.is_valid():
#i want hash messages in here and then save into database
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return redirect('manajemen_user')
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
data = {
'user_form': user_form,
'profile_form': profile_form,
'object_list': users
}
return render(request, template_name, data)
#jika session tidak ada
else:
return HttpResponseRedirect('/simofa/logout')
This is my html templates:
<form name="tambah_user" class="form-horizontal style-form" method="POST">{% csrf_token %}
<div class="form-group">
<label class="col-sm-2 col-sm-2 control-label">Nama User</label>
<div class="col-sm-10">
<!-- <input type="text" class='form-control'> -->
{{ user_form.username }}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 col-sm-2 control-label">Password</label>
<div class="col-sm-10">
{{ user_form.password }}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 col-sm-2 control-label">Messages</label>
<div class="col-sm-10">
{{ profile_form.messages }}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 col-sm-2 control-label">Hak Akses</label>
<div class="col-sm-10">
{{ profile_form.hak_akses }}
<br><br><br>
<button type="submit" class="btn btn-theme">Submit</button>
</div>
</div>
</form>
Hashing is not encrypting!
A hash is a function that converts one message to another. Consider a hash function (LAME_HASH) that just takes the count of the number of characters in a string.
LAME_HASH("TOOMANYSECRETS")
>>> 13
LAME_HASH("SETECASTRONOMY")
>>> 13
If I tell you my string is "TOOMANYSECRETS" and the hash was 10, you can immediately tell I am lying. But, if I tell you the hash is 13, you can't verify what the message is, it could be "TOOMANYSECRETS" or "SETECASTRONOMY". While this all seems trivial, this is essentially how hashing mechanisms like MD5 and SHA work.
There is no "decryption" of hashes, and if anyone tells you otherwise they are lying, or the entire security world would collective explode.
i can encrypt plain text to the md5 / sha1 with this
import hashlib
print hashlib.md5('test').hexdigest()
and that is the answer I was looking for

Categories