how to get users id in django model? - django

I need to get id from logged user to filter query in models.how to get users id in django model?
Thanks
in models.py:
class Portfo(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
sell = models.ForeignKey(Sell, on_delete=models.CASCADE, null=True)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True)
profit = models.PositiveIntegerField(null=True)
final_amount = models.IntegerField(null=True)
def __str__(self):
return self.product.name
def final_amount(self):
final_amount = 0
buy = Buy.objects.filter(product_id=self.product.id, owner__exact=...)
sell = Sell.objects.filter(product_id=self.product.id)

I need to get id from logged user to filter query in models.
Models are designed to be request-unaware. If you want to retrieve the user id, you will need to pass it through a parameter, so:
class Portfo(models.Model):
# …
def final_amount(self, user_id):
final_amount = 0
buy = Buy.objects.filter(product_id=self.product_id, owner_id=user_id)
sell = Sell.objects.filter(product_id=self.product_id, owner_id=user_id)
# …
In the view, you can then use the .final_amount(…) method, for example with:
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
#login_required
def some_view(request, pk):
my_porfolio = get_object_or_404(Portfolio, pk=pk)
final_amount = my_portfolio.final_amount(request.user.id)
# …

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})

How to make provide views and specify which users can GET it

I created the following model, with an author who is the user that created it and Title and description, with few other fields.
from django.db import models
from django.conf import settings
from django.utils import timezone
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=200)
added_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=300)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
added_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
# 🔴 who_can_see
who_can_see = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name='tweet_user', blank=True)
def __str__(self):
return self.title
now I want to filter books based on who_can_see and auther
My question is: how to modify this books = Book.objects.filter(added_by=user) in order to get only the posts that have the authenticated username included in the who_can_see field.
in models.py i created this field to add the usernames that can see the view who_can_see = models.ManyToManyField( settings.AUTH_USER_MODEL, related_name='tweet_user', blank=True), but I don't know how to filter views based on them, also users can see all books even when they are not loggedin
#api_view(["POST"])
#csrf_exempt
#permission_classes([IsAuthenticated])
def add_book(request):
print({"request.data": request.data})
payload = request.data
user = request.user
try:
author = Author.objects.get(id=payload["author"])
book = Book.objects.create(
title=payload["title"],
description=payload["description"],
added_by=user,
author=author,
who_can_see=payload["who_can_see"] # 🔴
)
serializer = BookSerializer(book)
return JsonResponse({'books': serializer.data}, safe=False, status=status.HTTP_201_CREATED)
except ObjectDoesNotExist as e:
return JsonResponse({'error': str(e)}, safe=False, status=status.HTTP_404_NOT_FOUND)
except Exception:
return JsonResponse({'error': 'Something terrible went wrong'}, safe=False, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
#api_view(["GET"])
#csrf_exempt
#permission_classes([IsAuthenticated])
def get_books(request):
# here maybe I need other arguments than request to get the other filed, in order to create if statements.
user = request.user.id
# books = Book.objects.filter(added_by=user)
books = Book.objects.filter(who_can_see=user, added_by=user) # 🔴 after i created this user who are not logged in can see the all private books.
serializer = BookSerializer(books, many=True)
return JsonResponse({'books': serializer.data}, safe=False, status=status.HTTP_200_OK)
You have to write query in which you have to check for which book current user is in who_can_see field. You can write this like this.
from django.db.models import Q
current_user = request.user
books = Book.objects.filter(Q(Q(added_by=user) | Q(who_can_see=current_user)))
if you want to get books for which who_can_see is empty
books = Book.objects.filter(Q(Q(added_by=user) | Q(who_can_see=current_user) | Q(who_can_see=None)))

Filtering Django models by user & object

I'm learning Django with a dummy example but having difficulty in understanding how to correctly filter my Django models by an authorised user in my views.
In my view I want to list the transactions associated with a users portfolio. The code below runs but when trying to access the result of 't' I get the error:
'ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing.'
Any help would be much appreciated, thanks.
if request.user.is_authenticated:
# Get model data
pf = Portfolio.objects.filter(user=request.user)
t = Transaction.objects.filter(pf=pf)
My model is as below:
from django.db import models
from django.contrib.auth.models import User
class Portfolio(models.Model):
# Portfolio has one user associated with it
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, default='-')
def __str__(self):
return self.name
class Transaction(models.Model):
# Transaction has one equity associated with it
equity = models.ForeignKey('Equity', on_delete=models.CASCADE, null=True)
# Transaction has one portfolio associated with it
pf = models.ForeignKey('Portfolio', on_delete=models.CASCADE)
BUY = 'BUY'
SELL = 'SELL'
BUY_OR_SELL = (
(BUY, 'BUY'),
(SELL, 'SELL'),
)
action = models.CharField(choices=BUY_OR_SELL, default=BUY, max_length=5)
num = models.FloatField(default=1)
price = models.FloatField(default=0)
date = models.DateField('date')
fee = models.FloatField(default=0)
def __str__(self):
return f'{self.equity}, {self.num}x{self.price}, {self.date:%d %b %Y}'
class Equity(models.Model):
class Meta:
verbose_name_plural = "Equities"
CUR_EUR = 'EUR'
CUR_GBP = 'GBP'
CUR_USD = 'USD'
CURRENCY_CHOICES = (
(CUR_EUR, 'EUR'),
(CUR_GBP, 'GBP'),
(CUR_USD, 'USD'),
)
symbol = models.CharField(max_length=20, default='-')
exchange = models.CharField(max_length=100, default='-')
currency = models.CharField(max_length=15, choices=CURRENCY_CHOICES, default=CUR_USD)
def __str__(self):
return self.symbol
Many thanks!
pf is here a collection of Portfolio objects, so you can query it with the __in lookup [Django-doc]:
Transaction.objects.filter(pf__in=pf)
Or if you are not interested in the Porfolio objects itself, you can make a query like:
Transaction.objects.filter(pf__user=request.user)
The query below will result in a query like:
SELECT transaction.*
FROM transaction
JOIN portfolio ON transaction.pf_id = portfolio.id
WHERE porfolio.user_id = 123
(with 123 the id of the request.user)

Dynamically update fields in django

When I create new sesid in session I need all the courses to add to the sesid in Registration model.
I am creating a result management system using django.
What I want to do is to
create a session (it is done)
then automatically, all the courses from course model will be in the
session model ( I don't need to add individually) and then show a
page that enables to add batch to the added courses.
After submission all the students of the corresponding batch will be
added to the course and thus session and redirect to somewhere to enable user to assign each course to a specific teacher
each of the students have several marks fields to cover by the assigned teacher
the result will be calculated and saved in the database after input from a table (better as an imported excel file)
so far, I have made this:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Course(models.Model):
cid = models.AutoField(primary_key=True)
cnam = models.CharField(max_length=200)
cidn = models.IntegerField()
cred = models.IntegerField()
def __str__(self):
return 'IT-' + str(self.cidn) + ' - ' + self.cnam
class Student(models.Model):
snam = models.CharField(max_length=200)
sid = models.AutoField(primary_key=True)
sroll = models.IntegerField()
sreg = models.IntegerField()
sbtc = models.IntegerField()
sses = models.CharField(max_length=10)
def __str__(self):
return self.snam
class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=200, null=True)
umob = models.CharField(max_length=20, blank=True, default='')
ulogo = models.ImageField(upload_to='media', blank=True)
def __str__(self):
return self.user.username
def createprofile(selfsender, **kwargs):
if kwargs['created']:
user_profile = Teacher.objects.creeate(user=kwargs['instance'])
class Session(models.Model):
sesid = models.IntegerField(primary_key=True,verbose_name= ('Session'))
def __str__(self):
return str(self.sesid)
def get_absolute_url(selfself):
return reverse('Dashboard:session')
class Registration(models.Model):
session = models.ForeignKey(Session, on_delete=models.CASCADE)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
# def __str__(self):
# return str(self.session.sesid) + ' - ' + 'IT-' + self.str(course.cidn) + ' - ' + self.course.cnam + ' - ' + self.str(Teacher.user)
class Result(models.Model):
reg = models.ForeignKey(Registration, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
ct1 = models.FloatField(null=True, blank=True)
ct2 = models.FloatField(null=True, blank=True)
ct3 = models.FloatField(null=True, blank=True)
asn = models.FloatField(null=True, blank=True)
# avg
atd = models.IntegerField(null=True, blank=True)
#total
def __str__(self):
return str(self.reg.session) + ' - ' + 'IT-' + str(self.reg.course.cidn) + ' - ' + self.student.snam
views.py:
from django.urls import reverse_lazy
from django.views import generic
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import CreateView
from django.shortcuts import render, redirect
from django_tables2 import RequestConfig
from .tables import *
from .models import *
from .forms import CustomUserChangeForm
class Login(generic.CreateView):
form_class = CustomUserChangeForm
success_url = reverse_lazy('index')
template_name = 'Dashboard/login.html'
class IndexView(ListView):
template_name = 'Dashboard/index.html'
def get_queryset(self):
return Course.objects.all()
def course(request):
table = CourseTable(Course.objects.all())
RequestConfig(request).configure(table)
return render(request, 'Dashboard/course.html', {'table': table})
def teacher(request):
table = TeacherTable(Teacher.objects.all())
RequestConfig(request).configure(table)
return render(request, 'Dashboard/teacher.html', {'table' : table})
def student(request):
table = StudentTable(Student.objects.all())
RequestConfig(request).configure(table)
return render(request, 'Dashboard/student.html', {'table' : table})
def result(request):
table = ResultTable(Result.objects.all())
RequestConfig(request).configure(table)
return render(request, 'Dashboard/result.html', {'table' : table})
class SessionView(CreateView,ListView):
template_name = 'Dashboard/createSession.html'
model = Session
fields = ['sesid']
def get_queryset(self):
return Session.objects.all()
How can I approach to the dynamic update of database?
Based on the explanation in the comment, something like this should do the trick.
For reusability, you could also move the for course... bit to a method on Session, such as add_courses(self, teacher): ...
class SessionView(CreateView, ListView):
template_name = 'Dashboard/createSession.html'
model = Session
queryset = Session.objects.all()
fields = ['sesid']
def form_valid(self, form): # this will be the creation form
instance = form.save() # save the empty session
for course in Course.objects.all():
Registration.objects.create(
session=instance,
course=course,
teacher=self.request.user.teacher, # (Is this correct?)
)
return HttpResponseRedirect(self.get_success_url())

Query for retrieve data with user fk Django 1.11

I'm trying to retrieve data from user. I have my model like this:
from django.db import models
from django.contrib.auth.models import User
Create your models here.
class informacionFacturacion(models.Model):
usuario = models.ForeignKey(User)
apellidos = models.CharField(max_length=100, default="editar")
nombres = models.CharField(max_length=100, default="editar")
telefono = models.CharField(max_length=100, default="editar")
email = models.EmailField(default="editar", null=False)
direccion_1 = models.CharField(max_length=100, default="editar")
direccion_2 = models.CharField(max_length=100, null=True, blank=True)
provincia = models.CharField(max_length=100, default="editar")
ciudad = models.CharField(max_length=100, default="editar")
codigoPostal = models.CharField(max_length=100, default="editar")
empresa = models.CharField(max_length=100, default="editar")
def __str__(self):
return self.usuario
My form for update user information:
from .models import informacionFacturacion
class informacionFacturacionForm(ModelForm):
class Meta:
model = informacionFacturacion
fields = [
"usuario",
"apellidos",
"nombres",
"telefono",
"email",
"direccion_1",
"direccion_2",
"provincia",
"ciudad",
"codigoPostal",
"empresa",
]
And in my view I have my query like this
from django.contrib.auth.decorators import login_required
from .models import informacionFacturacion
from .forms import informacionFacturacionForm
#login_required
def datosPersonales(request):
form = informacionFacturacionForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
query = informacionFacturacion.objects.filter(usuario=request.user)
context = {
"titulo": "Datos personales | Cadenas Giordanino S.R.L" + request.user.username,
"body_class": "class= sidebar_main_open sidebar_main_swipe",
"form": form,
"infoFacturacion": query,
}
template = "micuenta/datosPersonales.html"
return render(request, template, context)
And this QuerySet is empty.
I need to retrieve this data in the user profile
**UPDATE: ** Full code on post.
**UPDATE 2: ** For displaying the user data on profile, im using a "For loop". This data, is retrieved in "value=" attr of html inputs. If the user has no data, the form dosnt show.
This is the way I wanna show the data. I populated this form from the same form u see here.
Here's when i enter for first time to my profile with no data
Thanks a lot.
Are you sure that request.user is the user you've linked your anotherModel to? If you aren't currently logged in then request.user will be an instance of AnonymousUser. See more in the Documentation: https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.HttpRequest.user
You can use the Django Shell for testing your models:
$ python manage.py shell
Then make some models:
from django.contrib.auth.models import User
from models import AnotherModel
# Grab a User
user = User.objects.first()
# Create a new anotherModel, linking the user
my_model = AnotherModel(
user=user,
address="whatever"
)
my_model.save()
my_model.user == user
>>> True