Hi I'm building a Webshop with a cart and checkout function. And I want to save data into a database.
Here are my models:
This is the model I want to save the data in:
class MessageItem(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
mItem = models.CharField(max_length=255, null=True)
mQuantity = models.CharField(max_length=255, null=True) # Could also be an Integer!
mOrderItem = models.CharField(max_length=255, null=True)
After I did that I want to call the data in another view and pass it into a sendmail() message variable. Does anyone know how I could do that?
Here are my other models:
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False) # Nicht nötig
image = models.ImageField(null=True, blank=True)
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=False)
transaction_id = models.CharField(max_length=200, null=True)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
Here is my View: I Want to save: item.product.name, item.quantity and items into the model.
#login_required(login_url='login')
def cart(request):
# If user logged in or not (Handling orders in cart)
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
for item in items:
SMES = item.product.name, str(item.quantity), items
print(SMES)
context = {'items': items, 'order': order, 'cartItems': cartItems}
return render(request, 'store/cart.html', context)
And this is the other view with the Sendmail() function:
#login_required(login_url='login')
def checkout(request):
if request.method == "POST":
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
message_name = request.POST['message-name']
message_email = request.POST['message-email']
message = request.POST['message']
message_to_send = str(message)
# send an email
send_mail(
'message from ' + message_name, # subject
message_to_send, # message
message_email, # from email
['jeampo#outlook.de'], # To Email
)
Thanks for any help!
your question is not fully understood. Do I understand correctly that:
in your for-loop in the cart view you want to save each orderitem of the incompleted customer's order in a MessageItem instance?
for item in items:
item_data = {'customer':customer,
'mItem':item.product.name,
'mQuantity':str(item.quantity),
'mOrderItem': '',} #Not sure what you want with items
message_item = MessageItem(**item_data)
message_item.save()
items is currently a queryset your looping over, and mOrderItem needs a string. So that one doesn't match yet.
I'm not sure if I'm getting the goal of your MessageItem object. Currently each time you call it a new MessageItem is created for each exisiting OrderItem in scope. create_or_update is probably what you want in this situation? Please clarify your goal to better understand the question at hand.
Related
I am working on a Django project which is something similar to Fiverr in its working. I have used abstractuser where there is a buyer and seller. The seller creates a gig then the buyer will go through the gig before placing an order. My issue is how to get the seller and place him in the order that the buyer will create from reading the gig. Currently I am using the system whereby the buyer will have to manually choose a gig from a list, which I think is not effective.
Here is my Models.py
`class User(AbstractUser):
is_buyer=models.BooleanField(default=False)
is_seller=models.BooleanField(default=False)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(default='avatar.jpg', null=True, blank=True)
about = models.CharField(max_length=100)
def __str__(self):
return self.user.username
class Gig(models.Model):
seller = models.ForeignKey(Profile, on_delete = models.CASCADE, null=False, blank=False)
category = models.ForeignKey('Category', on_delete = models.CASCADE, null=False, blank=False)
title = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
gig_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Order(models.Model):
buyer = models.ForeignKey(Profile, on_delete=models.CASCADE, null=False, blank=False)
seller = models.ForeignKey(Gig, on_delete=models.CASCADE, related_name='+', null=False, blank=False)
title = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500)
amount = models.IntegerField(max_length=50, blank=False)
is_ordered = models.BooleanField(default=False)
order_id = models.UUIDField(default=uuid.uuid4, unique=True, db_index=True, editable=False)
slug = models.SlugField(null=True)
def __str__(self):
return self.title`
And views.py where I am getting the submissions;
def createOrder(request):
profile = request.user.profile
form = CreateOrderForm()
if request.method == 'POST':
form = CreateOrderForm(request.POST, request.FILES)
if form.is_valid:
order = form.save(commit=False)
order.buyer = profile
order.save()
# form.save()
messages.info(request, 'Order Succesfully Created')
return redirect('create_order')
else:
messages.error(request, 'Order Not Created! Try Again Later')
context = {'form':form}
return render(request, 'users/create_order.html', context)
Any help will he highly appreciated.
Im getting a NOT NULL constraint error in my code when trying to save my model form, even though the fields I have left empty are optional (have set blank=True, null=True) in models.py
Im very confused, what am I doing wrong?
The error is popping up when I leave the first optional field blank (description). Filling any of them manually before work.save() pushes the issue to the next field, and passes when all fields are filled.
EDIT: this also happens when trying to create a work instance from the admin dashboard.
models.py
class Work(models.Model):
## core fields
creator = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True,
default=None)
created = models.DateTimeField()
modified = models.DateTimeField()
work_slug = models.SlugField(max_length=50) # slug -> TBD: find way to assign default value to slug = archival number.
archive = models.ForeignKey(Archive, on_delete=models.CASCADE)
# superfolder -> replaces category, series etc with dynamic hierarchical database
folder = models.ForeignKey(Folder, on_delete=models.CASCADE)
# basic metadata fields
name = models.CharField(max_length=50)
year = models.CharField(max_length=50)
medium = models.CharField(max_length=50)
description = models.CharField(max_length=1200, blank=True, null=True)
# optional metadata
authors = models.CharField(max_length=50, blank=True, null=True)
classification = models.CharField(max_length=50, blank=True, null=True)
location = models.CharField(max_length=50, blank=True, null=True)
link = models.URLField(max_length=50, blank=True, null=True)
record_creator = models.CharField(max_length=50, blank=True, null=True) # revisit ->
# custom descriptors
cd1_name = models.CharField(max_length=50, blank=True, null=True)
cd1_value = models.CharField(max_length=50, blank=True, null=True)
cd2_name = models.CharField(max_length=50, blank=True, null=True)
cd2_value = models.CharField(max_length=50, blank=True, null=True)
cd3_name = models.CharField(max_length=50, blank=True, null=True)
cd3_value = models.CharField(max_length=50, blank=True, null=True)
cd4_name = models.CharField(max_length=50, blank=True, null=True)
cd4_value = models.CharField(max_length=50, blank=True, null=True)
cd5_name = models.CharField(max_length=50, blank=True, null=True)
cd5_value = models.CharField(max_length=50, blank=True, null=True)
cd6_name = models.CharField(max_length=50, blank=True, null=True)
cd6_value = models.CharField(max_length=50, blank=True, null=True)
cd7_name = models.CharField(max_length=50, blank=True, null=True)
cd7_value = models.CharField(max_length=50, blank=True, null=True)
# Standardized Metadata
# Methods
def __str__(self):
return 'Work: {}'.format(self.name)
def save(self, *args, **kwargs):
''' On save, update timestamps '''
user = get_current_user()
if not self.id: # if the model is being created for the first time:
self.creator = user # assign the currently logged in user as the creator
self.created = timezone.now() # set the 'created' field to the current date and time
# self.slug = **archival id of work (automatically determined)**
self.modified = timezone.now() # set the modified field to the current date and time. This is reassigned everytime the model is updated.
return super(Work, self).save(*args, **kwargs)
forms.py
class WorkForm(ModelForm):
class Meta:
model = Work
fields = ['name', 'year', 'medium', 'description', 'authors', 'classification', 'location', 'link', 'record_creator', 'cd1_name', 'cd1_value', 'cd2_name', 'cd2_value', 'cd3_name', 'cd3_value', 'cd4_name', 'cd4_value', 'cd5_name', 'cd5_value', 'cd6_name', 'cd6_value', 'cd7_name', 'cd7_value']
views.py
def add_work(request, folder_pk):
'''
Add a work to the filesystem.
folder_pk: the primary key of the parent folder
Checks if the user is logged in and if the user is the creator of the folder. If so, the user is allowed to add a work to the folder. Otherwise, the user is redirected to the login page.
'''
# add work to the database
parent = Folder.objects.get(pk=folder_pk)
mediaFormSet = modelformset_factory(MediaFile, fields=('name', 'alt_text', 'caption', 'media'), extra=1)
if request.method == "POST" and parent.archive.creator == get_current_user():
# if the form has been submitted
# Serve the form -> request.POST
form = WorkForm(request.POST)
# mediaFormSet = mediaFormSet(request.POST)
if form.is_valid(): # if the all the fields on the form pass validation
# Generate archival ID for work
# archival ID is random, unique 6 digit number that identifies the work
archival_id = get_archival_id()
# create a new work with the parameters retrieved from the form. currently logged in user is automatically linked
work = form.save(commit=False)
work.work_slug = archival_id
work.folder=parent
work.archive=parent.archive
work.save()
# Redirect to dashboard page
return redirect('add_media_to_work', work_pk=work.pk)
else:
# If the form is not submitted (page is loaded for example)
# -> Serve the empty form
form = WorkForm()
return render(request, "archival/add_edit_work.html", {"workForm": form})
i was facing the same problem as you, i made a sign up form, and it was giving me the same error because the .save() method was getting executed before i fill in the fields, there was no data to save, because of that: the fields type was None. so i just implemented an if else statement to make sure that the .save() method won't be executed if the type of the field isnNone,
here is a snippet:
if field == None:
pass
else:
form.save()
I have a method that creates orders from the user's cart. For the courier to take an order from different restaurants, the order is divided into several. But at the moment I'm splitting the order just by the dish in the cart. How to make an order split by restaurants? that is, if a user orders 5 dishes from two different restaurants, then 2 orders were formed.
views.py
#action(methods=['PUT'], detail=False, url_path='current_customer_cart/add_to_order')
def add_cart_to_order(self, *args, **kwargs):
cart = Cart.objects.get(owner=self.request.user.customer)
cart_meals = CartMeal.objects.filter(cart=cart)
data = self.request.data
for cart_meal in cart_meals:
order = Order.objects.create(customer=self.request.user.customer,
cart_meal=cart_meal,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.save()
return response.Response({"detail": "Order is created", "added": True})
models.py
class Order(models.Model):
"""User's order"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='related_orders')
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
cart_meal = models.ForeignKey(CartMeal, on_delete=models.CASCADE, null=True, blank=True)
restaurant_address = models.CharField(max_length=1024, null=True)
address = models.CharField(max_length=1024)
status = models.CharField(max_length=100, choices=STATUS_CHOICES, default=STATUS_NEW)
created_at = models.DateTimeField(auto_now=True)
delivered_at = models.DateTimeField(null=True, blank=True)
courier = models.OneToOneField('Courier', on_delete=models.SET_NULL, null=True, blank=True)
class CartMeal(models.Model):
"""Cart Meal"""
user = models.ForeignKey('Customer', on_delete=models.CASCADE)
cart = models.ForeignKey('Cart', verbose_name='Cart', on_delete=models.CASCADE, related_name='related_meals')
meal = models.ForeignKey(Meal, verbose_name='Meal', on_delete=models.CASCADE)
qty = models.IntegerField(default=1)
final_price = models.DecimalField(max_digits=9, decimal_places=2)
class Meal(models.Model):
"""Meal"""
title = models.CharField(max_length=255)
description = models.TextField(default='The description will be later')
price = models.DecimalField(max_digits=9, decimal_places=2)
discount = models.IntegerField(default=0)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, null=True)
slug = models.SlugField(unique=True)
class Restaurant(models.Model):
"""Restaurant"""
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
address = models.CharField(max_length=1024)
owner = models.ForeignKey('Restaurateur', on_delete=models.CASCADE, null=True)
meals = models.ManyToManyField('Meal', related_name='related_restaurant', blank=True)
How can I do this, please help me
You can group your meals with respect to resturants.
import itertools
from core.models import CartMeal, Order
for restaurant, cart_meals in itertools.groupby(CartMeal.objects.order_by('meal__restaurant'), lambda s: s.meal.restaurant):
order = Order.objects.create(
customer=self.request.user.customer,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.cart_meal.set([cart_meal for cart_meal in cart_meals])
Ref: The answer is formulated by taking help from following answer.
https://stackoverflow.com/a/57897654/14005534
I have a Django website and part of it lists data in rows with the primary key in one of the columns. This works great except for when I have separate users. I'm using foreign keys in each model to separate the different user's data. My problem is that the data for each user has to have a number in the column that increments numerically and does not have any spacing, for instance, 1,2,3,5 is bad. If User1 is uploading data and halfway through User2 uploads a row of data then if I use the primary key the numbers will not be in numerical order for each user and will read 1,2,3,5 for User1 and 4 for User2. I tried forloop counter but I need the numbers all the be assigned to the row and not change if one is deleted. Ive been at this for 2 weeks and am having a really hard time describing my problem. I think I need somesort of Custom User Primary Key, a primary key for each user. Any help at this point is greatly appreciated, Thanks!
I finally figured it out after about a week.
models.py:
class Sheet_Building(models.Model):
user = models.ForeignKey(User, default=True, related_name="Building", on_delete=models.PROTECT)
count_building = models.IntegerField(blank=True, null=True)
date = models.DateField(blank=True, null=True, verbose_name='Inspection Date')
time = models.TimeField(blank=True, null=True, verbose_name='Inspection Time')
inspection_type = models.CharField(max_length=16, choices=INSPECTION_TYPE_BI, blank=True, null=True, verbose_name='Inspection Type')
flname = models.CharField(max_length=25, blank=True, null=True, verbose_name='Inspector')
report_date = models.DateField(blank=True, null=True, verbose_name='Report Date')
department = models.CharField(max_length=29, choices=DEPARTMENT_BI, blank=True, null=True, verbose_name='Department')
responsible_name = models.CharField(max_length=25, blank=True, null=True, verbose_name='Responsible Person')
building_address = models.CharField(max_length=52, choices=BUILDING_ADDRESS, blank=True, null=True, verbose_name='Building and Address')
floor = models.CharField(max_length=8, choices=FLOOR_LEVEL_BI, blank=True, null=True, verbose_name='Floor / Level')
room = models.CharField(max_length=35, blank=True, null=True, verbose_name='Area / Room')
location = models.CharField(max_length=10, choices=LOCATION_BI, blank=True, null=True, verbose_name='Location')
priority = models.IntegerField(blank=True, null=True, verbose_name='Priority')
hazard_level = models.CharField(max_length=20, choices=HAZARD_LEVEL_BI, blank=True, null=True, verbose_name='Hazard Level')
concern = models.CharField(max_length=31, choices=CONCERN_BI, blank=True, null=True, verbose_name='Concern')
codes = models.CharField(max_length=51, choices=CODES_BI, blank=True, null=True, verbose_name='Element and Code')
correction = models.TextField(max_length=160, blank=True, null=True, verbose_name='Corrective Action')
image = models.ImageField(blank=True, null=True, verbose_name='Image', upload_to='gallery')
notes = models.TextField(max_length=500, blank=True, null=True, verbose_name="Inspector's note")
class Meta:
ordering = ['-pk']
def __str__(self):
return self.flname or 'None'
def get_absolute_url(self):
return reverse('list_building')
view.py:
def adddata_building(response):
if response.method == 'POST':
form = SheetForm_Building(response.POST, response.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.user = response.user #User
if Sheet_Building.objects.filter(user=response.user).values_list('count_building'):
instance.count_building = Sheet_Building.objects.filter(user=response.user).aggregate(count_building=Max('count_building'))['count_building'] + 1 #Count
else:
instance.count_building = 1
instance.save()
response.user.Building.add(instance)
return redirect('list_building')
else:
form = SheetForm_Building()
return render(response, 'sheets/add_data/add_data_building.html', {'form': form})
HTML:
{% for post in object_list %}
{{ post.count_building }}
{% enfor %}
I am trying to create cart using django but i am getting this error. while I try to check that the user is authenticated or no i used customer = request.user.customer but it says user has no attribute customer
Here is my views.py
def cart(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = OrderModel.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
items = []
context = {}
return render(request, 'Home/cart.html', context)
here is my models.py
class CustomerModel(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='')
customer_name = models.CharField(max_length=1000, null=True)
customer_phone = models.CharField(max_length=20, null=True)
def __str__(self):
return self.customer_name
class OrderModel(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order_date = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False,null=True,blank=True)
transaction_id = models.CharField(max_length=1000, null=True)
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
product = models.ForeignKey(ProductModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
class Address(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
address = models.CharField(max_length=10000)
city = models.CharField(max_length=1000)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
I am stuck here and cant understand what to do.
I think changing the line customer = request.user.customer to customer = request.user.customermodel may solve your problem. If you want to use customer = request.user.customer add related name to your CustomerModel's field:
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer')
Note: Make sure that your user object has a related profile.
For example add an extra condition to your codes like following:
if hasattr(request.user, 'customer'): # If you have related name otherwise use customermodel
customer = request.user.customer
else:
# Return a proper message here
Because if your user object has no related profile this line of code will raise RelatedObjectDoesNotExist error type.
For the user field of the CustomerModel, you must set "related_name" and "related_query_name" to "customer":
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer', related_query_name='customer')
You have to set the "related_name" parameter in your CustomerModel customer field for reverse access
user = models.OneToOneField(User, related_name="user", on_delete = models.CASCADE, null=True, blank=True, default='')
if you don't set the related name django will generate field name + "_set" for the access (user_set in your example)