class Account(models.Model):
accountId = models.CharField(max_length=20, primary_key=True)
username = models.CharField(max_length=30)
def __str__(self):
return self.username
class Project(models.Model):
projectId = models.CharField(max_length=20, primary_key=True, default=idgen)
projectName = models.CharField(max_length=20)
projectOwner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="owner")
projectSize = models.IntegerField(default=25)
projectGuests = models.ManyToManyField(User, related_name="guests")
projectAccounts = models.ManyToManyField(Account, "accounts")
def __str__(self):
return self.projectId
In this code, users can have multiple projects and projects can have multiple accounts. Is there any way to pass just the 'user' to the template (or without passing anything since we can get the user using the request) to get all the accounts in all the projects that the user owns without using a for loop? cause I have to display a count of accounts in total that the user owns.
for example, if the user had 2 projects and each project had 2 accounts... is there any way to get the final value 4 in the template just using the user object?
Try this Query
accounts = Project.objects.filter(projectOwner=request.user).projectAccounts_set.all()
It is best to perform such arithmetic in Django views rather than templates 21404051.
First select all Projects related to request.user by
projects = Project.objects.filter(projectOwner=request.user)
.annotate(pc = Count('projectAccounts'))
.aggregate(total = Sum('pc'))
Now in template
{{ projects.total }}
I decided to do it in views.py after all since it looks impossible to do in templates.
accs = []
for project in request.user.owner.all():
for account in project.projectAccounts.all():
accs.append(account)
accs = list( dict.fromkeys(accs))
this was a simple solution. pretty sure there are way easier and more efficient ways to do this.
Related
how would I go about automatically generating a list of objects in the database for DJango?
Example model:
#models.py
class Book(models.Model):
BOOKS = (
('0','Secret Life of Bees'),
('1','Pride and Prejudice')
)
name = models.CharField(max_length=100, choices=BOOKS)
def __str__(self):
return self.name
class Library(models.Model):
librarian = models.OneToOneField(UserProfile, on_delete=models.CASCADE, primary_key=True)
books = models.ManyToManyField(Book)
How would I automatically add all the books to the database so I don't have to manually add them using the admin control panel?
Update! To anyone who doesn't know how to do this, you can call Object.objects.bulk_create(Object([Object(property=propertyInfo),Object(property=propertyInfo)]).
I have 2 types of users on my site, one is the store owner, I want to log him in with the usual custom user email and password, the other is the buyer, I want to login the buyer using just a pin number only. Is it possible to have both types of login users in the same django app. Thanks in advance.
class Store(models.Model):
store_name = models.CharField(max_length=200)
store_status = models.BooleanField()
store_details = models.CharField(max_length=300, blank = True)
store_balance = models.IntegerField(default=0)
user = models.OneToOneField(User, on_delete=models.CASCADE)
college = models.ForeignKey(Institute, on_delete=models.CASCADE )
def __str__(self):
return str(self.store_name)+" "+ str(self.store_status)
class Customer(models.Model):
name = models.CharField(max_length=200)
branch = models.CharField(max_length=200, choices=BRANCHES)
sem = models.CharField(max_length=200, choices=SEMESTERS)
reg_no = models.IntegerField(default=0)
balance = models.IntegerField(default=0)
pin_no = models.IntegerField()
college = models.ForeignKey(Institute, on_delete=models.CASCADE )
To make a custom authentication you need to add an Authentication Backend. Firstly your customer model is not related to your user model try adding a OnetoOne field in that. After that try adding code like this in one of your apps:-
from django.contrib.auth.backends import BaseBackend
class MyBackend(BaseBackend):
def authenticate(self, request, token=None):
try:
customer = Customer.objects.get(pin_no=token)
user = customer.user
except Customer.DoesNotExist:
return None
return user
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Refer the documentation on Customizing authentication in Django for more information.
Now after making an AuthenticationBackend you need to make it so that Django uses it, you do this by adding it to AUTHENTICATION_BACKENDS in your settings.py, since you want the default username and password to remain something like this would work:
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend', 'path.to.MyBackend']
You have several ways for this. One is making an index place where they choose the option "owner" or "buyer" and after ask for login auth. Other approach is to make url specifying those options already. If you want to do it in the same "form" you could add specification under the hood for manage this input data provided also could be done by several ways, or make a checkbox like so it changes form input. Choose the one that suits you. Does this help you?
Currently, if you’re logged in, you’ll be able to see all the products, no matter
which user you’re logged in as.how can i show merchants only the products that belongs to them.
i try this
views.py
def users_homepage(request):
product=Product.objects.filter(merchant=request.user).order_by('date_added')
and i get this error " Cannot query "mustapha": Must be "Merchant" instance"
my models.py
class Merchant(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE, primary_key=True)
class Product(models.Model):
merchant=models.ForeignKey(Merchant, on_delete=models.CASCADE)
date_added = models.DateTimeField(auto_now_add=True)
Use user to get a merchant instance and the use that to query products.
def users_homepage(request):
merchant = Merchant.objects.get(user=request.user)
product = Product.objects.filter(merchant=merchant).order_by('date_added')
Another way to do this is using [default] related name.
def users_homepage(request):
product = Product.objects.filter(merchant=request.user.merchant).order_by('date_added')
Try
def users_homepage(request):
product=Product.objects.filter(merchant__user=request.user).order_by('date_added')
I'm new to Django so I make 3 simple tables to return a WishList. The thing is that I want whenever user asks for WishList, his/her user_id is used to make a SELECT query to return his/her own WishList. And I want to get product title and product url from my WishList table. I'm using to_field but with that way I only can get product title back. I don't know much about Django so help me!
Product
class Product(models.Model):
class Meta:
unique_together = (('id', 'title'),)
title = models.CharField(max_length=200, unique=True,
help_text='Name of the product')
url = models.CharField(max_length=300, default='',
help_text='Url of the product')
def __str__(self):
return 'Product: {}'.format(self.title)
WishList
class WishList(models.Model):
class Meta:
unique_together = (('user', 'product'),)
user = models.ForeignKey(fbuser,
on_delete=models.CASCADE,
help_text='Facebook user',
to_field='user_id')
product = models.ForeignKey(Product, to_field='title', db_column='title',
on_delete=models.CASCADE)
def __str__(self):
return 'WishList: {}'.format(self.user)
It's not a good practice to override to_field to another field different than your model.pk unless you have a really good reason and you know what you are doing (definitely not the case right now).
So after you read the docs, you will know that in order to get wishlisht related to a user, you can use the ForeignKey reverse relation to get all related wishlists for a user.
user_wishlists = my_user.wishlist_set.all()
#Because we know that you want to access the wishlist.products
#in order to optimize things (in terms of db queries)
#you can add and .select_related('product')
#e.g, user_wishlists = my_user.wishlist_set.all().select_related('product')
#now follow the wishlist.product foreign key to access the related product for every wishlist
for wishlist in user_wishlists:
product = wishlist.product
print (product.id, product.title, product.url)
Now after you read a little bit more of the documentation
you will notice that your WishList model is in fact an intermediate model for a ManyToMany relation between User and his wished products, then you will know that you can define a M2M field between user and products via WishList like so:
class FbUser(models.Model):
#...
wished_products = models.ManyToManyField(
Product,
through='WishList',
through_fields=('user', 'product')
)
#and now accessing user wished products would be easy as:
user_wished_products = my_user.wished_products.all()
for product in user_wished_products:
print (product.id, product.title, product.url)
I am building a project in Django. It's like a blog page where a user can post journals and photos. I am trying to make a page where everything the person posted is displayed in chronological order. My simplified models.py is shown below.
class Writing(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
date_created = models.BigIntegerField(default=0)
class Photo(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
date_created = models.BigIntegerField(default=0)
In this case, I would have to touch two database tables, and then order them by date_created. I heard that I can use itertools chain to loop through these two tables, but I am not sure exactly how. What should I write in views.py?
It's simple in the views.py you can for example:
def my_view(request):
writing = Writing.objects.filter(user=request.user).order_by('-date_created')
photos = Photo.objects.filter(user=request.user).order_by('-date_created')
context = {'writing': writing, 'photos': photos}
return render(request, 'your_template.html', context)
One more hint you shouldn't use BigIntegerField for date, instead of it use DateTime
date_created = models.DateTimeField(auto_now_add=True, blank=True)