M2M relation ship : Can't save to the through model - django

i have a an order model which is in m2m relationship with a product model, when i create an order, and after checking my DB, i can see the order saved but not in the through model
models.py
from inventory.models import Product
from user.models import User
class Order(models.Model):
product = models.ManyToManyField(Product, through='OrderItems' )
vendeur = models.ForeignKey(User, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
class Customer(models.Model):
full_name = models.CharField(max_length=60, verbose_name='full name')
address = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
city = models.CharField(max_length=30)
class OrderItems(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order,on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
views.py
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})
forms.py
class NewOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ('product','quantity')

if you use save(commit=False), Calling save_m2m() is required.
because your form has a m2m field
refer to documentions
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
form.save_m2m()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})

Related

How can i submit two forms in django

I have a template where i should have 2 forms and update them, I succeded to get the 2 foms in the same template, but when i make changes nothing happens !
forms.py
class OrderManageForm(forms.ModelForm):
class Meta:
model = Order
fields = ['customer', 'product', 'quantity', 'status']
class CustomerForm(forms.ModelForm):
address = forms.CharField(widget=forms.Textarea(attrs={'rows': 5}))
class Meta:
model = Customer
fields = ['full_name', 'address', 'phone', 'city', 'email'
models.py
class Customer(models.Model):
full_name = models.CharField(max_length=150)
address = models.CharField(max_length=1500, null=True)
phone = models.CharField(max_length=20)
city = models.CharField(max_length=100)
email = models.EmailField(null=True)
def __str__(self):
return self.full_name
class Order (models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE,)
quantity = models.IntegerField(default=1)
status = models.TextField(choices=ORDER_STATUS, default='Pending')
def __str__(self):
return 'Order n°: ' + str(self.id)
views.py
def update_order(request, order_id):
order = get_object_or_404(Order, id=order_id)
cust = get_object_or_404(Customer, order__id=order_id)
if request.method == 'POST':
customer = CustomerForm(request.POST)
form = OrderManageForm(request.POST)
print(request.POST)
if form.is_valid() and customer.is_valid():
order = form.save(commit=False)
customer = customer.save()
order.customer = customer
order.save()
return redirect('orders')
else:
form = OrderManageForm(instance=order)
customer = CustomerForm(instance=cust)
return render(request, 'dashboard/order_details.html', {'form': form, 'customer': customer})
I put the 2 forms in only one form tag inside my HTML template
You need to feed the instances to the forms such that the forms can update the corresponding records:
def update_order(request, order_id):
order = get_object_or_404(Order, id=order_id)
cust = order.customer
if request.method == 'POST':
customer = CustomerForm(request.POST, instance=cust)
form = OrderManageForm(request.POST, instance=order)
if form.is_valid() and customer.is_valid():
form.save()
customer.save()
return redirect('orders')
# …
You should only redirect in case the two forms are valid, otherwise you can not see the errors that appear on the form. Furthermore you shoudld remove the customer from the fields of the OrderManageForm:
class OrderManageForm(forms.ModelForm):
class Meta:
model = Order
fields = ['product', 'quantity', 'status'] ← no customer

ModelForm inserts number in foreign key field

I have model from which I created a ModelForm:
models.py:
class City(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class Profile(models.Profile):
name = models.CharField(max_length=50)
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=False)
location = models.ForeignKey('City', on_delete=models.SET_NULL, blank=True, null=True)
forms.py
from django import forms
from .models import Profile, City
class LocationField(forms.CharField):
def clean(self, value):
try:
city = City.objects.get(name=value)
except ObjectDoesNotExist:
city = City.objects.create(name=value)
return city
class ProfileForm(forms.ModelForm):
location = LocationField()
class Meta:
model = Profile
exclude = ['user']
views.py
def profile_update_view(request):
template_name = 'profiles/update.html'
user = request.user
profile = Profile.objects.get(user__id=user.id)
if request.method == 'GET':
form = ProfileForm(instance=profile)
else:
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
obj = form.save(commit=False)
obj.user = user
obj.save()
return redirect('profile_view')
context = {'form': form}
return render(request, template_name, context=context)
When I'm saving form, I'm satisfied how it's working, but when I load form again to update in, it fills LocationField() as an City pk integer, but I want it to load name instead. Is there a way to do this?
I've added in views.py:
if request.method == 'GET':
initial = {}
if profile.location:
initial = {'location': profile.location.name}
form = ProfileForm(instance=profile, initial=initial)
now it's working. But it's some workaround. I've thought there is some parameter maybe

How to add condition on Django model foreign key?

I am new in Django, would you please help me, I have two models, by name of Continent and Country, in the Country form I want to only display the Continents in the dropdown list which their status is true?
models
from django.db import models
from smart_selects.db_fields import GroupedForeignKey, ChainedForeignKey
class Continent(models.Model):
name = models.CharField(max_length=255)
status=models.BooleanField(default=True)
def __str__(self):
return self.name
class Country(models.Model):
continent = models.ForeignKey(Continent, null=True, on_delete=models.SET_NULL)
status=models.BooleanField(default=True)
name = models.CharField(max_length=255)
def __str__(self):
return self.name
forms
class FormContinent(ModelForm):
class Meta:
model = Continent
fields = '__all__'
class FormCountry(ModelForm):
class Meta:
model = Country
fields = '__all__'
views
def continent(request):
form = FormContinent()
if request.method == 'POST':
form = FormContinent(request.POST)
form.is_valid()
form.save()
return redirect('/continent')
else:
context = {'form': form}
return render(request, 'continent.html', context)
def country(request):
form = FormCountry()
if request.method == 'POST':
form = FormCountry(request.POST)
form.is_valid()
form.save()
return redirect('/country')
else:
context = {'form': form}
return render(request, 'country.html', context)
You can make use of the limit_choices_to=… parameter [Django-doc]:
class Country(models.Model):
continent = models.ForeignKey(
Continent,
# ↓ limit choices to Continents with status=True
limit_choices_to={'status': True},
null=True,
on_delete=models.SET_NULL
)
# …

Can't get owner as foreign key to my model -- django

I'm trying to do a form so a user can upload a video, the problem is i can't get current user or it's id as a foreign key on my video model
Error: IntegrityError
Exception Value: (1048, "Column 'owner_id' cannot be null")
How can i solve the problem please, i looked at django documentation but doesn't find answer.
My models.py:
class Videowtm(models.Model):
name = models.CharField(max_length=50, blank=True)
description = models.CharField(max_length=255, blank=True)
uploaded_at = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)
video = models.FileField(upload_to='videos/')
My forms.py:
class VideowtmForm(forms.ModelForm):
class Meta:
model = Videowtm
fields = ('name', 'description', 'video', )
My views:
#login_required
def model_form_upload(request):
if request.method == 'POST':
form = VideowtmForm(request.POST, request.FILES)
form.owner = request.user
if form.is_valid():
form.save()
return redirect('home')
else:
form = VideowtmForm()
return render(request, 'model_form_upload.html', {
'form': form
})
Try this one:
first add blank=True to the owner in your model:
###No need for this if you don't include it in your form fields###
class Videowtm(models.Model):
name = models.CharField(max_length=50, blank=True)
description = models.CharField(max_length=255, blank=True)
uploaded_at = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=True)
video = models.FileField(upload_to='videos/')
and then:
views.py:
#login_required
def model_form_upload(request):
if request.method == 'POST':
form = VideowtmForm(request.POST, request.FILES)
if form.is_valid():
video = form.save(commit=False)
video.owner = request.user
video.save()
return redirect('home')
else:
form = VideowtmForm()
return render(request, 'model_form_upload.html', {
'form': form
})

Saving modelform with user id?

I have a question concerning a new project I'm creating. To put it simply, the website has user accounts, and each user has the ability to create a simple paragraph. The form is functioning perfectly, but I can't seem to assign the user's ID to the saved form.
model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
class Thoughts(models.Model):
user = models.ForeignKey(UserProfile, null=True)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
forms.py
class ThoughtForm(ModelForm):
class Meta:
model = Thoughts
fields = ['title', 'description']
views.py
#login_required(login_url='sign_in')
def add_thought(request):
context = {}
populateContext(request, context)
user_details = UserProfile.objects.get(user=request.user)
context.update(user_details=user_details)
if request.method == 'POST':
new_thought_form = ThoughtForm(request.POST)
if new_thought_form.is_valid():
new_thought_form.save()
return HttpResponse('Hurray, saved!')
else:
new_thought_form = ThoughtForm()
c = {'new_thought_form': new_thought_form,}
c.update(csrf(request))
return render_to_response('lala/add_new_thought.html', c)
Whenever I try adding "instance=user_details.id", it says that the 'int' object has no attribute '_meta'. Any thoughts?
You can simplify the models by removing the UserProfile model:
# models.py
class Thoughts(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
Your forms.py looks good.
Change your views:
# views.py
#login_required(login_url='sign_in')
def add_thought(request):
if request.method == 'POST':
form = ThoughtForm(request.POST)
if form.is_valid():
thought = form.save(commit=False)
thought.user = request.user
thought.save()
return HttpResponse('Hurray, saved!')
else:
form = ThoughtForm()
return render(request, 'lala/add_new_thought.html', {
'form': form
})