Saving new model overrides existing model - python

I have a form that I am using to create new models, but every time I submit the form, it overrides the only existing model in the database.
My form view:
class createItinerary(CreateView):
template = "create.html"
form_class = CreateItineraryForm
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template, {"form": form})
def post(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
form = self.form_class(request.POST)
if form.is_valid():
destination = form.cleaned_data.get("destination")
trip_length = form.cleaned_data.get("trip_length")
start = form.cleaned_data.get("start")
end = form.cleaned_data.get("end")
sights = form.cleaned_data.get("sights")
new = Itinerary(destination=destination,
trip_length=trip_length, start=start, end=end)
new.sights.set(sights)
new.save()
return redirect("/")
else:
form = CreateItineraryForm
return render(request, self.template, {"form" : form})
My forms.py:
from django import forms
from django.forms.widgets import *
from itineraries.models import Itinerary
from sights.models import Sight
sight_choices = ()
for sight in Sight.objects.all():
new_sight = (("%s" % sight.name, "%s" % sight.name))
sight_choices += new_sight
class CreateItineraryForm(forms.ModelForm):
class Meta:
model = Itinerary
exclude = []
destination = forms.CharField(label="Destination", max_length=100)
start = forms.DateField(widget=NumberInput(attrs={"type" : "date"}))
end = forms.DateField(widget=NumberInput(attrs={"type" : "date"}))
sights = forms.ModelMultipleChoiceField(
queryset=Sight.objects.all())
My models.py:
from django.db import models
from sights.models import Sight
import datetime
class Itinerary(models.Model):
id = models.AutoField(primary_key=True, default=0)
destination = models.CharField(max_length=100, null=False)
trip_length = models.IntegerField(null=False)
start = models.DateField()
end = models.DateField()
sights = models.ManyToManyField(Sight)
def __str__(self):
trip_name = "%s in %s days" % (self.destination, self.trip_length)
return trip_name
This is the only existing model in the database:
When I use the form to save a new one:
It replaces the old model with the newly created one every time.

Remove default=0 from id in your model.

Related

django / filter the fields of a form and have the error 'int' object has no attribute '_meta'

I use django-cities-light for a travel website and I would like to filter the cities in the fields ville_de_depart and ville_destination in the newBookingForm by trip.depart and trip.destination.
I tried to pass the trip object in the instance of newBookingForm. I override the __init__ and I took the value of the depart and destination, I succeeded in filtering the fields but I could no longer save the newBooking, the view redirect to the alltrip page with no error but no new booking is added to the database.
I tried to replace the trip by the slug which is the same value as the id and it shows me this error
'int' object has no attribute '_meta'
models.py
class trip(models.Model):
depart = models.ForeignKey(default='',to=Country,on_delete=models.CASCADE,related_name='depart')
destination = models.ForeignKey(default='',to=Country,on_delete=models.CASCADE)
date_de_depart = models.DateField(default='')
prix_kg = models.PositiveIntegerField(default='')
collecte = models.BooleanField(default=False,null=False,help_text='' )
creation_date = models.DateTimeField(auto_now=True)
author = models.ForeignKey(to=settings.AUTH_USER_MODEL,on_delete=models.CASCADE,default='')
slug = models.SlugField(max_length=100, default='' )
#jouter slug
def save(self, *args , **kwargs):
super(trip, self).save(*args , **kwargs)
if not self.slug:
self.slug = self.id
self.save()
def __str__(self):
return f'{self.id} {self.author} '
class Booking(models.Model):
trip = models.ForeignKey(trip,on_delete=models.CASCADE, default='',)
author = models.ForeignKey(to=settings.AUTH_USER_MODEL,on_delete=models.CASCADE,default='')
creation_date = models.DateTimeField(auto_now=True)
ville_de_depart = models.ForeignKey(City,on_delete=models.CASCADE,default='')
slug = models.SlugField(max_length=100, default='' )
# ville_depart = models.ForeignKey(default='',to=City,on_delete=models.CASCADE,related_name='ville_dep')
sender_phone = PhoneNumberField(blank=True)
receiver_phone = PhoneNumberField()
ville_destination = models.ForeignKey(default='',to=City,on_delete=models.CASCADE,related_name='ville_dest')
#jouter slug
def save(self, *args , **kwargs):
super(Booking, self).save(*args , **kwargs)
if not self.slug:
self.slug = self.id
self.save()
def __str__(self):
return str(self.trip.author)
views.py
def detailsTrip(request, slug):
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm(instance=slug)
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
if request.method == 'POST':
form = newBookingForm(request.POST , instance=slug )
if request.user.is_authenticated:
if form.is_valid():
trip = get_object_or_404(models.trip,slug=slug)
Booking = form.save(commit=False)
Booking.trip_id= trip.id
Booking.author_id = request.user.id
Booking = form.save()
return redirect('/alltrips')
else:
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm()
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
return render(request, 'detailstrip.html', context)
else:
return render (request, 'notFound.html')
return render(request,'detailstrip.html', context , )
forms.py
class newBookingForm(forms.ModelForm,):
def __init__(self,*args,**kwargs):
# capture the instance : Slug
slug = kwargs.get('instance')
# capture current trip
Trip = get_object_or_404(trip, id=slug)
# Filter cities field by the instance : trip.depart / trip.destination
super(newBookingForm, self).__init__(*args,**kwargs)
self.fields['ville_de_depart'].queryset = City.objects.filter(country_id=Trip.depart)
self.fields['ville_destination'].queryset = City.objects.filter(country_id=Trip.destination)
class Meta:
model = Booking
fields = ['ville_de_depart','ville_destination']
exclude = ['sender_phone','receiver_phone']
solution
#view.py
def detailsTrip(request, slug):
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
#add the trip to the form
bookingForm = newBookingForm(trip=trip)
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
if request.method == 'POST':
#add the object trip to the form here too
form = newBookingForm(trip,request.POST )
if request.user.is_authenticated:
if form.is_valid():
trip = get_object_or_404(models.trip,slug=slug)
Booking = form.save(commit=False)
Booking.trip_id= trip.id
Booking.author_id = request.user.id
Booking = form.save()
return redirect('/alltrips')
else:
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm()
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
return render(request, 'detailstrip.html', context)
else:
return render (request, 'notFound.html')
return render(request,'detailstrip.html', context , )
form.py
class newBookingForm(forms.ModelForm,):
class Meta:
model = Booking
fields = ['ville_de_depart','ville_destination']
exclude = ['sender_phone','receiver_phone']
def __init__(self,trip,*args,**kwargs):
# Filter cities field by trip.depart / trip.destination
super(newBookingForm, self).__init__(*args,**kwargs)
self.fields['ville_de_depart'].queryset = City.objects.filter(country=trip.depart)
self.fields['ville_destination'].queryset = City.objects.filter(country=trip.destination)
As long as you use many-to-many fields, you need to call form.save_m2m() after saving the model instance. or you can just call form.save() without commit=False keyword argument.
Here are some quotes from Django documentation:
This save() method accepts an optional commit keyword argument, which accepts either True or False. If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database.
Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation.
read this documentation about the save method

Django: Change the parent, when the child get deleted(unidirectional OneToOne)

I want to change Photo 'labeled' field False when I delete LabeledPhoto object.
#models.py
class Photo(models.Model):
image = models.ImageField(upload_to='shoes_data/%Y/%m/%d', name='image')
created = models.DateTimeField(auto_now_add=True)
labeled = models.BooleanField(default=False)
class LabeledPhoto(models.Model):
labeled_image = models.OneToOneField(Photo, on_delete=models.PROTECT, related_name='labeled_image')
topcategory = models.CharField(max_length=64)
subcategory = models.CharField(max_length=64)
labeler = models.CharField(max_length=32)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
I tried like this but, It didn't work
# views.py
class LabeledPhotoDelete(DeleteView):
model = LabeledPhoto
template_name = 'label/labeled_photo_delete.html'
success_url = reverse_lazy('photo:labeled_list')
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
labeled = LabeledPhoto.objects.get(id=self.object.pk)
labeled.labeled_image.labeled = False
labeled.save()
self.object.delete()
return reverse(success_url)
You need to .save() the Photo:
from django.http import HttpResponseRedirect
class LabeledPhotoDelete(DeleteView):
model = LabeledPhoto
template_name = 'label/labeled_photo_delete.html'
success_url = reverse_lazy('photo:labeled_list')
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
image = self.object.labeled_image
image.labeled = False
image.save()
self.object.delete()
return HttpResponseRedirect(success_url)
But there is no reason to store whether the image is labeled in a field: you can simply look that up if you want to know this. Indeed, you can add a property:
class Photo(models.Model):
image = models.ImageField(upload_to='shoes_data/%Y/%m/%d', name='image')
created = models.DateTimeField(auto_now_add=True)
#property
def labeled(self):
try:
return self.labeled_image is not None
except LabeledPhoto.DoesNotExist:
return False
or annotate the queryset with the fact if a LabeledPhoto exists:
from django.db.models import BooleanField, ExpressionWrapper, Q
Photo.objects.annotate(
is_labeled=ExpressionWrapper(
Q(labeled_image__isnull=False),
output_field=BooleanField()
)
)

Django DateTimeField and User Input fields not added

I am beginner to python Django. I'm working on practice project. I got stuck while adding a product.
Its adds all the fields except two fields
i. DateTimeField
ii. User (who add the product)
The error which i'm facing is:
django.db.utils.IntegrityError: null value in column "pub_date" violates not-null constraint
DETAIL: Failing row contains (3, Piano, Ball Pens(set of 3), 15, 30, 10, images/ballpens_QdhwoOa.jpg, null, null).
models.py
class Product(models.Model):
companyName = models.CharField(max_length=255)
pro_name = models.CharField(max_length=255)
Purchase_Price = models.IntegerField()
Sale_Price = models.IntegerField()
Quantity = models.IntegerField()
Picture = models.ImageField(upload_to='images/')
saler = models.ForeignKey(User, on_delete=models.CASCADE)
pub_date = models.DateTimeField()
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def __str__(self):
return self.pro_name
views.py
class AddProduct(TemplateView):
template_name = 'stock/addproduct.html'
def get(self, request):
form = AddProductForm()
args = {'form':form}
return render(request, self.template_name, args)
def post(self, request):
form = AddProductForm(request.POST, request.FILES)
if form.is_valid():
productadded = form.save()
productadded.saler = request.user
productadded.pub_date = timezone.datetime.now()
productadded.save()
return redirect('stock')
else:
args = {'form': form}
return render(request, self.template_name, args)
In views.py, I am saving a user and date and time as you see in above
forms.py
class AddProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('companyName', 'pro_name', 'Purchase_Price', 'Sale_Price', 'Quantity', 'Picture' )
def __init__(self, *args, **kwargs):
super(AddProductForm, self).__init__(*args, **kwargs)
self.fields['companyName'].label = 'Company Name'
self.fields['pro_name'].label = 'Product Name'
self.fields['Purchase_Price'].label = 'Purchase Price'
self.fields['Sale_Price'].label = 'Sale Price'
Your help will be appreciated.
Thank You
do a small correction
if form.is_valid():
productadded = form.save(commit=False)
productadded.saler = request.user
productadded.pub_date = timezone.datetime.now()
productadded.save()
return redirect('stock')

Django | making searchform to filter with multiple models

I'm trying to create a search form in my Django project that will filter multiple models(3) It works for a single model and an additional model tied by a foreign key. But,I can not combine different models query to one get_queryset.
forms.py
class SearchForm(forms.Form):
username=forms.CharField(
label = 'enterprise_id',
required = False
)
skill_name=forms.ModelChoiceField(
queryset=Skill_name.objects,
label='skill_list',
required=False
)
model.py
class EnterpriseID(models.Model):
enterprise_id = models.CharField('enterprise_id',max_length=40,blank=True,default="",)
def __str__(self):
return self.enterprise_id
class Skill_name(models.Model):
skill_name = models.CharField('skill_name',max_length=40,blank=False,null=False,)
def __str__(self):
return '{0}'.format(self.skill_name)
class Skill(models.Model):
enterprise_id = models.ForeignKey(EnterpriseID,verbose_name="enterprise_id",on_delete=models.PROTECT,)
skill_name=models.ForeignKey(Skill_name,verbose_name="skill_name",on_delete=models.PROTECT,)
def __str__(self):
return '{0}'.format(self.enterprise_id)
class Employee(models.Model):
# user = models.OneToOneField(accounts_models.AuthUser, on_delete=models.CASCADE, blank=True)
enterprise_id = models.ForeignKey(EnterpriseID,verbose_name="enterprise_id",on_delete=models.PROTECT,)
join_at = models.DateField('join_at',default="",null=True,blank=True)
def __str__(self):
return '{0}'.format(self.enterprise_id)
views.py
class PersonalInfoSearchView(LoginRequiredMixin,ListView):
model = Employee
template_name = 'personal_info/search_personal_info.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = SearchForm(self.request.GET)
return context
def get_queryset(self):
form = SearchForm(self.request.GET)
queryset = super().get_queryset()
if form.is_valid():
username = form.cleaned_data['username']
skill_name = form.cleaned_data['skill_name']
if username:
queryset=queryset.filter(enterprise_id__enterprise_id__icontains=username)
if skill_name:
skill_query =Skill.objects.filter(skill_name=skill_name)
return queryset.distinct()

Django: How to populate form data in template

So I am trying to have "two forms" in single class based view.
My view is:
class ListAndCreate(CreateView):
model = xmpp_buddy_groups
form_class = xmpp_buddy_groups_form
second_form_class = sip_extension_form
template_name = "xmpp/index.html"
success_url = reverse_lazy('xmpp:index')
def get_context_data(self, **kwargs):
context = super(ListAndCreate, self).get_context_data(**kwargs)
context['object_list'] = self.model.objects.all()
extension = SipExtension.objects.values_list('sip_extension', flat=True)
obj = SipExtension.objects.filter(sip_extension=1331).first()
for buddy_groups in group_names:
for sip in buddy_groups.sipextension_set.all():
sip_extension = sip.sip_extension
print(sip_extension)
context['extension'] = extension
SipExtension.objects.exclude(sip_extension__in=extension)
print(extension)
context['form'] = self.form_class
context['form2'] = self.second_form_class(instance=obj)
context['extensions'] = SipExtension.objects.exclude(sip_extension__in=extension)
return context
My form classes:
from django import forms
from .models import xmpp_buddy_groups
from extensions.models import SipExtension
class xmpp_buddy_groups_form(forms.ModelForm):
class Meta:
model = xmpp_buddy_groups
fields = ['group_name']
def __init__(self, *args, **kwargs):
super(xmpp_buddy_groups_form, self).__init__(*args, **kwargs)
self.fields['group_name'].required = False
class sip_extension_form(forms.ModelForm):
class Meta:
model = SipExtension
fields = ['real_name','sip_extension']
widgets = {
"sip_extension": forms.Select
}
def __init__(self, *args, **kwargs):
super(sip_extension_form, self).__init__(*args, **kwargs)
self.fields['sip_extension'].queryset = \
SipExtension.objects.filter(sip_extension=1331)
My models:
from django.db import models
from django.urls import reverse
class xmpp_buddy_groups(models.Model):
group_name = models.CharField(max_length=30,unique=True)
def __str__(self):
return '%s' % (self.group_name)
from django.db import models
class SipExtension(models.Model):
real_name = models.CharField(max_length=32)
sip_extension = models.PositiveIntegerField(unique=True)
sip_secret = models.CharField(max_length=32)
commlink_push = models.BooleanField(default=False)
default_did = models.ForeignKey('dids.DidNumber',null=True,blank=True)
xmpp = models.BooleanField(default=False)
xmpp_username = models.CharField(max_length=50,default='username')
xmpp_password = models.CharField(max_length=32,default='password')
xmpp_buddy_groups_names = models.ManyToManyField('xmpp.xmpp_buddy_groups')
def __str__(self):
return '%s : %s' % (self.sip_extension, self.real_name)
I am accessing form in template as {{form2.as_p}}. The dropdown appears empty. I want it to populate with 1331. How can I do that?
EDIT: Added models make the question clearer. Pardon my inexperience with Django

Categories

Resources