i am trying to build my first project, a CRM website to handle orders and inventory.
and i got stuck, i was able to link orders to customer.
but when i try to build order that contain multi items. for some reason i didn't find a way to do it.
hope you can assist me.
so I have User>>Order>>Multi Items.
questions:
1) does the best practice here is just use ForeignKey ?
this my model's code:
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
def date_createdview(self):
return self.date_created.strftime('%B %d %Y')
class Product(models.Model):
CATEGORY = (
('General', 'General'),
('SmartHome', 'SmartHome'),
('Software', 'Software'),
('Mobile', 'Mobile'),
)
name = models.CharField(verbose_name='שם', max_length=200, null=True)
price = models.FloatField(verbose_name='מחיר', null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY, verbose_name='קטגוריה')
description = models.CharField(max_length=200, null=True, verbose_name='מלל חופשי')
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('New', 'New'),
('Work in progress', 'Work in progress'),
('completed', 'completed'),
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def date_createdview(self):
return self.date_created.strftime('%d/%m/%Y')
class OrderItem(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE)
quantity = models.IntegerField(null=True)
2)how should I build my views or forms?
i want to make it dynamic, when i enter the order i can insert items and see the new item get add to a list of the items in the order.
how can save the order number and add new items?
this is my product view, it's working. I can add new products.
#login_required(login_url="login")
def products(request):
form = ProductForm(request.POST or None)
if form.is_valid():
form.save()
products = Product.objects.all()
context = {'form': form, 'products': products}
return render(request, 'accounts/products.html', context)
hope you can direct me to the right place.
thank you!
if form.is_valid():
order = get_object_or_404(Order, id=id)
instance = form.save(commit=False)
instance.order=order
instance.save()
just need to do:
commit=False
and then link the order.
Related
While creating new products I'm getting such kind of error. Can someone help me?
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name_geo = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.ForeignKey(Category, null=False, default=0, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name_geo
class Category(models.Model):
_id = models.AutoField(primary_key=True, editable=False)
name = models.CharField(max_length=200, null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
#api_view(['POST'])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category="Sample Category",
price=0,
brand='Sample Brand',
countInStock=0,
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
Without separating category class in models.py everything works fine. I mean If i didn't use ForeignKey in Products class for category
It just has to be a Category Instance/Object
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category=Category.objects.get_or_create(name="Sample Category"),
price=0,
brand='Sample Brand',
countInStock=0,
)
Notes:
You could just do a .get() or a .filter().first() if you don't want to create
If you use a form, you can get away with just the Category's PK/_id in the POST
this type of thing: f = form(request.POST) f.is_valid() f.save()
At the end that field will hold the PK/_id/Row# of the Category Obj
This the views.py file.
How can i display the appointments made by the current logged in user?
def user(request):
client = Client.objects.all()
appointments = Appointment.objects.all()
context = {'appointments': appointments, 'client': client,
}
return render(request, 'users/user.html', context)
Here is my Models.py. I need to display the appointments by a user when they are logged in to their profile.
class Appointment(models.Model):
CATEGORY = (
('Plumbing', 'Plumbing'),
('Electrical', 'Electrical'),
('Cleaning', 'Cleaning'),
)
STATUS = (
('Pending', 'Pending'),
('Delivered', 'Delivered'),
)
user = models.ForeignKey(Client, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200, null=True)
worker = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
task_date = models.DateField(_("Task Date"), blank=True, null=True)
task_location = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
budget = models.FloatField(null=True)
task_description = models.CharField(max_length=1000, null=True)
task_image = models.ImageField(
null=True, blank=True, help_text='Optional.')
def __str__(self):
return str(self.user)
instead of using all() in your query use filter()
all() gives you all the entries in the table.
do something like this:
appointments = Appointment.objects.filter(user = request.user)
the left side "user" inside the filter must be a column in the Appointment model/table. you can pass multiple parameters inside the filter.
Yea it worked. but i had to create a one to one relatioship between appointment and User
I want to get each product's total price in all orders which I mean how much each product sold in all orders. What Query should I write in views.py to display this matter in html?
this is my models.py:
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
description = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Shipping', 'Shipping'),
('Delivered', 'Delivered'),
)
# order will remain after customer deleted
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
note = models.CharField(max_length=200, null=True)
def __str__(self):
return self.product.name
and this is my views.py:
def home(request):
products = Product.objects.all()
orders = Order.objects.all()
total_order_prices = Order.objects.aggregate(Sum('price'))
orders.products = Product.objects.all().aggregate(Sum('price'))
context = {'orders':orders, 'products':products,'total_order_prices': total_order_prices }
return render(request, 'account/home.html', context)
Morez!
What I recommend is defining a foreign key to Order() in the Product(). Doing so would allow you to get related objects much more easily, as shown here.
All you would have to do is products = order.product_set.
Hope it helps!
Another question from me tonight and I hope I can explain it adequately:
I got three classes in my "models.py":
class Customer(models.Model):
full_name = models.CharField(max_length=100, null=True, unique=True)
short_name = models.CharField(max_length=8, null=True, unique=True)
class Project(models.Model):
customer = models.ForeignKey(Customer, null=False, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True, unique=True)
...
class Entry(models.Model):
user = models.ForeignKey(User, null=True, blank=False, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, null=True, blank=False, on_delete=models.CASCADE)
project = models.ForeignKey(Project, null=True, blank=False, on_delete=models.CASCADE)
date = models.DateField()
shortText = models.CharField(max_length=100, null=False, blank=False)
...
Note: One Customer can have multiple Projects.
On one of my sites there's a table with buttons beside each "Customer". The plan is, that it should lead me to another page, were the user can write and save his "Entry". Right now, the PrimaryKey inside the Button/Link contains the ID of the "Customer".
My question is: is it possible to limit the choices of the "Project" (inside a Drop-Down-Menu) to the "Customer" that has been clicked on? And is creating a ModelForm the right thing to do?
Thanks to all of you and a good night!
Well, don't know if this is the right way, but I found a solution for my problem:
Wrote a "forms.ModelForm" for my view-function...
class EntryForm(ModelForm):
class Meta:
model = Entry
fields = '__all__'
def __init__(self, *args, pk, **kwargs):
super().__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(customer_id=pk)
Insert my ModelForm into the view-function...
def WriteEntry(request, pk):
form = EntryForm(pk=pk)
if request.method =='POST':
form = EntryForm(request.POST, pk)
if form.is_valid():
form.save()
...
context = {'form': form}
return render(request, '...html', context)
I have 2 models, Item and OnHand. Item represents the product, like a USB Keyboard, while OnHand represents an actual USB Keyboard.
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=100)
manufacturer = models.ForeignKey(Manufacturer, blank=True, null=True, on_delete=models.SET_NULL)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
vendor = models.ForeignKey(Vendor, blank=True, null=True, on_delete=models.SET_NULL)
vendor_sku = models.CharField(max_length=80, default='000000000')
replenish_threshold = models.IntegerField(max_length=1000, default=10)
max_onhand = models.IntegerField(max_length=10000, default=30)
introduction = models.DateField(auto_now=True)
tags = models.ManyToManyField(Tag)
slug = models.SlugField(max_length=100, default=slugify(name))
class Meta:
verbose_name_plural = 'items'
def __str__(self):
return self.name
class OnHand(models.Model):
name = models.CharField(max_length=100)
serial = models.CharField(max_length=80, default='Consumable')
asset = models.CharField(max_length=20, null=True, blank=True)
product = models.ForeignKey(Item, blank=True, null=True, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag)
class Meta:
verbose_name_plural = 'items on hand'
def __str__(self):
if not self.serial:
return self.name
return self.serial
I have a ModelForm I use for adding new Items and OnHand, the form I'm working with is at /inventory/add_onhand// so /inventory/add_onhand/1/ would be the form to add a keyboard to inventory for Item with a primary key of 1.
class OnHandForm(forms.ModelForm):
class Meta:
model = OnHand
fields = {'name', 'asset', 'serial',}
def add_onhand(request, query):
if request.method == "POST":
form = OnHandForm(request.POST)
if form.is_valid():
form.save()
return redirect('view_item')
else:
print(query)
form = OnHandForm()
item = Item.objects.get(pk=query)
return render(request, 'add_onhand.html', {'form':form, 'item':item})
When saving a new OnHand via this form, how would I direct the relationship to Item?
I am still hoping for a better solution, but in the meantime what I've done was added product to the form, but using JQuery to hide the element and automatically select it based on the Item's primary key.
This is hacky, but it works. I'd hope for a more elegant solution.