local variable 'user' referenced before assignment but I assigned user.id - django

I have created a function to set a boelian to false :
def verification(request, user_id):
#get currently logged in user
user = request.user
user = user.objects.get(pk=user_id)
user.profile.first_visit = False
user = user.objects.get(pk=user_id)
user.save()
return redirect('create-workspace')
I added this to my template
{% url 'firstvisit' user.id %}
And this to my path
path('first_visit/<user_id>', views.verification, name="firstvisit")
My models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
group = models.OneToOneField(Group, null=True, blank=True, on_delete=models.CASCADE)
manager = models.BooleanField(default=False)
first_visit = models.BooleanField(default=True)
So everything looks in order, but it says user is not assign...
What did i do wrong ?

I'm assuming this is what you're trying to achieve and I think your issue might be that you are querying the wrong table for what you want:
def verification(request, user_id):
#get currently logged in user
user_profile = Profile.objects.get(user_id=user_id)
user_profile.first_visit = False
user_profile.save()
return redirect('create-workspace')

Related

django add object with the current user

I'm trying to create a todoapp with google login to create personal todolist for each users.
here's views.py
from django.contrib.auth.decorators import login_required
#login_required
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user.id)
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'])
add_new_item.save()
return HttpResponseRedirect('/home/')
this is my code before without users but when there's currently login user it's throwing this error
null value in column "id" violates not-null constraint / DETAIL: Failing row contains (null, sampletodo,null). I believe the third column which is null is the userid and first column null is auto increment id since I set it to id SERIAL primary key in todoitem table
I'm 100% sure i need to add something #addTodo views.py, I just dont know how to add todolist with the current user
EDIT here's my models.py
class Todoitem(models.Model):
content = models.CharField(max_length=100)
userid = models.ForeignKey(AuthUser, models.DO_NOTHING,
db_column='userid')
class Meta:
managed = False
db_table = 'todoitem'
class AuthUser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
username = models.CharField(unique=True, max_length=150)
soon...
class Meta:
managed = False
db_table = 'auth_user'
Just pass the current user the same way you did in todoView. The request object has a reference to the current user through request.user. But you need to specify the user object, not user.id
#login_required
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user) # changed to request.user
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'], userid=request.user)
add_new_item.save()
return HttpResponseRedirect('/home/')
You should use a good user model to be able to use request.user.
Try a model like this:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
username = models.CharField(unique=True, max_length=150)
then in your views you can do this
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'], userid=request.user)
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user) # changed to request.user
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})

Autofill my author field with foreign key

I am trying to autofill my user foreign key in my note project with authentication in django. I tried, but it's not working and asking that owner is required field. Please, help! Thanks in an advance.
views.py
#login_required(login_url='login')
def index(request):
tasks = Task.objects.filter(owner=request.user)
form = TaskForm()
if request.method=='POST':
form = TaskForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.owner = request.user
instance.save()
context = {
'tasks':tasks,
'form':form,
}
return render(request, 'list.html',context)
models.py
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.title
Since you fill in the owner yourself, it makes no sense to specify the owner as a form field. You thus should exclude it, and let this be handled by the view. The form thus looks like:
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ['owner']
If no ModelForm will need to specify the owner, you can mark the field as non-editable:
class Task(models.Model):
# …
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
# …

How to use one view by two different users in django?

I have a custom user model as below:
class CustomUser(AbstractUser):
username = None
email = EmailField(verbose_name='email address', max_length=255, unique=True, )
first_name = CharField(verbose_name='First Name', max_length=30, null=True, )
middle_name = CharField(verbose_name='Middle Name', max_length=30, null=True, blank=True, )
last_name = CharField(verbose_name='Last Name', max_length=30, null=True, )
phone_number = CharField(verbose_name='Phone Number', max_length=30, null=True, )
is_partner = BooleanField(default=False, )
is_student = BooleanField(default=False, )
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
As shown above, a user can be a student or can be a partner, who will be in charge of a few students and have access to their assets.
The partner model is as below:
class Partner(Model):
user = OneToOneField(CustomUser, on_delete=CASCADE)
partner_name = CharField(max_length=100, )
The student model is as below:
class Student(Model):
user = OneToOneField(CustomUser, on_delete=CASCADE)
student_name = CharField(max_length=100, )
partner = ForeignKey(Partner, on_delete=SET_NULL, null=True)
As shown, in the Student model, partner can be null. The reason is that a student can either directly enroll in the system without having a partner or he/she can be enrolled by a partner. A student might even specify a partner that is optional when he/she is enrolling.
I have a student view and url pattern:
path('student_profile/', student_profile, name='student_profile')
def student_profile(request):
user = request.user
student = get_object_or_404(Student, user=user)
return HttpResponse('The student will do AAAAAA')
I have a url pattern and partner view:
path('partner_profile/', partner_profile, name='partner_profile')
def partner_profile(request):
user = request.user
partner = get_object_or_404(Partner, user=user)
return HttpResponse('The partner will do some stuff such as updating his/her profile')
there is this url pattern and view that allowes a partner to see his/her list of student:
path('partners/<int:partner_pk>/students/', partner_students, name='partner_students')
def partner_students(request):
template_name = 'partners/partner_students.html'
context = {}
partner = get_object_or_404(Partner, user=request.user)
partner_students = Student.objects.filter(partner=partner)
context.update({'partner_students': partner_students})
return render(request, template_name, context)
in template, I can have this url path:
path('students/<int:student_pk>/', partner_student_profile, name='partner_student_profile')
{% for student in partner_students %}
student.pk
{% endfor %}
What I need is that somehow, instead of rewriting a view to do some stuff with the student profile, I use the one that is already written.
I want to use this:
def student_profile(request):
user = request.user
student = get_object_or_404(Student, user=user)
return HttpResponse('The student will do some stuff such as updating his/her profile')
I do not want to write this:
def partner_student_profile(request, student_pk):
student = Student.objects.get(pk=student_pk)
return HttpResponse('The partner will do AAAAAA for his/her student')
I want to reuse the already written "student_profile" view
Have a url like this.
path('profile/<str:profile_type>/<int:pk>', profile_view, name='profile_view')
Now create a view to map to this url.
def profile_view(request, profile_type: str, pk: int):
user = request.user
if profile_type == 'partner':
"""
do something
"""
template_name = 'partner_handler.html'
context = dict()
elif profile_type == 'student':
"""
do something
"""
template_name = 'student_handler.html'
context = dict()
return render(request, template_name, context)
So basically, you are using two url path parameters to check what type of profile you want to work with, in your case it's going to be a student or partner. Depending on the profile type you can choose your own template and build your own context to pass to the chosen template.
Hope it helps!

How to filter a (or all) joined table's rows by the current logged in user in django?

My creation is a basic project about ticketing, users and assets. It's a typical application that companies have to keep a list of who has what and what issues are occurring.
So far I have (models):
**** Tickets ******************
class Ticket(models.Model):
category = models.ForeignKey('TicketCategory')
issue = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True,null=True,related_name="tickets")
owner = models.ForeignKey(User)
**** Users *********************
class Users(models.Model):
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
email = models.CharField(max_length=100, blank=True)
business = models.ForeignKey('Business', blank=True, null=True,related_name="users")
owner = models.ForeignKey(User)
class Meta:
db_table = 'users'
verbose_name_plural = "users"
ordering = ["lastname"]
**** Assets *********************
class Assets(models.Model):
serial = models.CharField(unique=False, max_length=100)
brand = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True, null=True, related_name="assets")
location = models.ForeignKey('AssetLocation', blank=False, null=False, related_name="assets")
owner = models.ForeignKey(User)
I have stripped them down a bit to exclude the useless info. There are others also like AssetsLocations, Categories etc., all of them in the same pattern - the owner is added in the end as a Foreign Key.
I have created some form of authentication, so every logged in user will have his own tickets, assets, and users (employees actually). Filtering is needed so the data of each user ONLY are displayed after every successful authentication.
I am using CBVs and override the get_queryset to enable filtering by the user currently logged in:
Views.py
class TicketList(ListView):
template_name = 'assets/ticket_list.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id).select_related('user','asset','category')
def get_context_data(self, **kwargs):
context = super(TicketList, self).get_context_data(**kwargs)
context['totalTickets'] = self.get_queryset().count()
context['tickets'] = self.get_queryset().select_related('user','asset','category')
return context
Everything works successfully and only logged_in user's data are shown. Then I am trying to create a new Ticket:
class TicketCreate(CreateView):
fields = [ 'category', 'issue', 'user']
template_name = 'assets/ticket_form.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.owner_id = self.request.user.id
self.object.save()
return HttpResponseRedirect(self.get_success_url())
success_url = reverse_lazy('ticket_list')
I am getting everything posted in the form template by using {{ form.category }}, {{ form.issue }} etc. The issue I am facing is that the drop-down boxes displayed in the form, for example the {{ form.user }} should be displaying only the users where user.owner = self.request.user.id, in simple words: the users that the owner created. Instead of it, all the users in the database are displayed.
Isn't it obvious which is the question :) ?

How to take user id from the form or database in Django?

I have a simple form login.html in Django. I take username and password from the login form and use to validate in my Django view:
def login_upload(request):
if request.method == 'POST':
username = request.POST['username']
username1 = ''.join(username)
password = request.POST['password']
password = ''.join(password)
password1 = hashlib.sha1(password).hexdigest()
user = authenticate(username=username1, password=password1)
user_id = request.galaxyuser.id
if len(user) > 0:
return render_to_response('right.html', {'user_id':user_id}, context_instance=RequestContext(request))
else:
return render_to_response('wrong.html', context_instance=RequestContext(request))
else:
return render_to_response('login.html', context_instance=RequestContext(request))
I also want to get the id of the user which I have to use later. I tried using:
user_id = request.galaxyuser.id
But it returns None value. Here's my models.py:
class GalaxyUser(models.Model):
id = models.IntegerField(primary_key=True)
create_time = models.DateTimeField(null=True, blank=True)
update_time = models.DateTimeField(null=True, blank=True)
email = models.CharField(max_length=765)
password = models.CharField(max_length=120)
external = models.IntegerField(null=True, blank=True)
deleted = models.IntegerField(null=True, blank=True)
purged = models.IntegerField(null=True, blank=True)
username = models.CharField(max_length=765, blank=True)
form_values_id = models.IntegerField(null=True, blank=True)
disk_usage = models.DecimalField(null=True, max_digits=16, decimal_places=0, blank=True)
class Meta:
db_table = u'galaxy_user'
Edit:
My custom authentication function:
def authenticate(username='username', password='password'):
return GalaxyUser.objects.filter(username=username, password=password)
I have no idea what request.galaxyuser is supposed to be, but given a user object, the id is an attribute of that object. The authenticate function is supposed to return a User object if the credentials are valid.
user = authenticate(username=username1, password=password1)
user_id = request.galaxyuser.id # what are you doing here?
user_id = user.id # this is the user ID.
This question might have different answers depending on how you implemented your custom User class. I'm assuming it's the class returned by authenticate.
Update:
Your example shows you returning a QuerySet (a .filter) which is a list of rows.
You need to either return one object so that you can do look up the ID attribute, or you need to modify the view to account for this strange behavior. Authenticate is supposed to return the authenticated user object, so I woul ddo the former.
def authenticate(.....):
try:
return GalaxyUser.objects.get(username=username, password=password)
except GalaxyUser.DoesNotExist:
return None
user = authenticate(...)
user_id = user.id