Django: How to properly make shopping cart? ( Array string field ) - python

Lately I've been needing to create a server-side shopping cart for my website that can have products inside. I could add cart and product in session cookies, but I prefer to add it to my custom made User model, so it can stay when the user decides to log out and log back in.
Since I'm making a shopping cart, I need to make a model for it, that will hold products as objects, so then they can be easily used, but I can't find any way to do so properly.
class User(models.Model):
username = models.CharField(max_length=150)
joined = models.DateTimeField('registered')
avatar = models.CharField(max_length=300)
balance = models.IntegerField(default=0)
ban = models.BooleanField()
cart = models.???
def __str__(self):
return self.username
How can I achieve having array string in models with using Django's system? If not then can it be possible by other libraries ( Json, Pickle ), but I've seen it can be done by ForeignKey, if so how is it possible?

I'd suggest using DB relationships instead of storing a string or an array of strings for this problem.
If you solve the problem using DB relationships, you'll need to use a ManyToManyField.
class User(models.Model):
...
cart = models.ManyToManyField(Product)
And assuming you have a model for your products.
class Product(models.Model):
name = models.CharField(max_length=30)
price = models.DecimalField(max_digits=8, decimal_places=2)
When adding elements to the cart you'll use something like this.
tv = Product(name='LED TV', ...)
tv.save()
diego = User.objects.get(username='dalleng')
diego.cart.add(some_product)

Related

How make users own their data in django

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

Using multiple columns as ForeignKey to return in another table

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)

Django auto save m2m relationship in form using through table

I have a m2m relationship between Servers and Products in Django with a through table called ServerProducts.
class ServerProduct(TimeStampedModel):
# Additional fields may be required in the future
server = models.ForeignKey('Server', on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
class Server(TimeStampedModel):
name = models.CharField(max_length=35)
# ...
products = models.ManyToManyField('Product', through='ServerProduct',
related_name='products', blank=True)
class Product(TimeStampedModel):
name = models.CharField(max_length=45, unique=True)
# ...
servers = models.ManyToManyField(
'Server', through='ServerProduct', related_name='servers')
In my view I have a form which allows users to create a Server and select from a list of all products for the Server to be associted with.
In order to create the ServerProduct objects (for the through table) on each save I have to write the following code inside save().
class ServerForm(forms.ModelForm):
class Meta:
model = Server
fields = '__all__'
def save(self, commit=True):
instance = super(ServerForm, self).save(commit=False)
instance.save()
if instance.products.count():
instance.products.clear()
for product in self.cleaned_data['products']:
ServerProduct.objects.create(server=instance, product=product)
return instance
I want to be able to reuse the form for both Create and Update views. Hence why I have to check if the current Server is associated with any products, and then do instance.products.clear(). To make sure it removes any previous products if they get deselected by a user.
This entire process feels unecessary, especially when I've read a lot about Django's built-in form.save_m2m() method. My question is, is there a simpler way do achieve what I'm doing using Django built-in's?

Optionally retrieve related items in Django REST framework

Suppose I have these models:
class House(models.Model):
name = models.CharField(max_length=50)
# Other attributes
class Booking(models.Model):
house = models.ForeignKey(House, on_delete=models.CASCADE)
arrival_date = models.DateField()
departure_date = models.DateField()
Serializers:
class HouseSerializer(serializers.ModelSerializer):
class Meta:
model = House
fields = ('id','name')
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = ('id',
'arrival_date',
'departure_date',
'house')
As you can see, bookings are associated to houses.
Users can request information about a house through "/house/:houseId", and bookings through "/booking/:bookingId".
I'd like to return all bookings related to a house when a user requests "/house/bookings", but these should NOT be returned when simply requesting "/house/bookings" as this is a relatively expensive operation and not usually needed.
I know how to make them be returned with the house, but how to make this optional. How do I do that?
First, it makes more sense (to me at least) to have your endpoint for bookings for a given house exist at /house/:houseId/bookings/ since the namespace at /house/bookings/ will already be looking for an ID.
You can also serialize the relationship between a House and Booking to display bookings for a house at the house detail endpoint. Something like:
class HouseSerializer(serializers.ModelSerializer):
bookings = BookingSerializer(many=True)
class Meta:
model = House
fields = ('id','name', 'bookings',)
But if you want another endpoint, just create a view that takes the BookingSerializer and filters the queryset by the House ID in the kwargs:
(Again, assuming your endpoint is /house/<house_id>/bookings/)
class BookingsForHouseListView(ListAPIView):
serializer_class = BookingSerializer
def get_queryset(self):
return Bookings.objects.filter(house__id=self.kwargs['house_id'])
Maybe you can do two serializers, one to the List of houses without showing the books, and another for the individual house, showing the books.
In the views you define the list serializer for the list uri, and the individual serializer for the individual uri.
Turns out, I was trying with too high-level parts of the API that restricted me more than they were helping me, I needed to do some things manually.
This answer https://stackoverflow.com/a/17763864/1582024 shows how to implement a hierarchy of resources.

Query Django model using name from another model

I'm building a project that involves a list of people and the transactions they've made. Each person will have their own profile with x amount of transactions.
My database, so far, consists of two models:
One to define a person
class Person (models.Model):
"""
A person
"""
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, blank=True)
def __unicode__(self):
return self.name
One to associate a transaction each person made.
class Purchase (models.Model):
"""
A purchase for each person
"""
person_id = models.ForeignKey(Person)
purchase_description = models.CharField(max_length=1000, blank=True)
I determined this would be a many-to-one database relationship because some people might make the same transaction.
Now, I can make pages for each person, showing their name in the header. What I'd like to do is show the transactions made to that particular person. How can this be done? Here's what my view.py file looks like:
from django.shortcuts import render
from .models import Person, Purchase
def load_person(request, name):
person = Person.objects.get(name=name)
# name = Purchase.objects.filter(purchase)
context = {
'name': name
# 'purchase': purchase
}
return render(request, 'pages/person.html', context)
Here's the url associated to the query in my url.py file.
url(r'^project/(?P<name>[-\w]+)/$', views.load_person),
person = Person.objects.get(name=name)
purchases = Purchase.objects.filter(person_id=person)
Sounds like you just started using django, there are several things that are not best practice, they are:
You don't need to define id in Person, django will define it for you.
Try not to use person_id as field name, use person instead. Django model is not relational database design, think of the models as separate entities.

Categories

Resources