django.db.utils.IntegrityError: NOT NULL constraint failed: user.id - python

I don't know why the error is caused even though I designated the author.
I'd appreciate your help.
model & form
class SuperTitle(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='debate_author')
super_title = models.CharField(max_length=100)
liker = models.ManyToManyField(User, related_name='debate_liker')
def __str__(self):
return self.super_title
class SuptitForm(forms.ModelForm):
class Meta:
model = SuperTitle
fields = ['super_title']
views.py
def create(request):
...
dic = {'super_title' : request.POST.get('sup_title')}
sup_form = SuptitForm(dic)
if sup_form.is_valid():
sup_form.author = request.user
sup_form.super_title = ...
sup_form.save()
...
return
IntegrityError at /polls/debate/create/
NOT NULL constraint failed: polls_supertitle.author_id

You get this error becouse you want to save form(create new SuperTitle objetd in database) without author.
You need to pass author objectd or id somehow to form. If the request.user is author i recommend form:
class SuptitForm(forms.ModelForm):
class Meta:
model = SuperTitle
fields = ['super_title', 'author']
widgets = {'author': forms.HiddenInput()}
and in view:
def create(request):
if request.method == 'POST':
sup_form = SuptitForm(request.POST)
if sup_form.is_valid():
sup_form.save()
else:
sup_form = SuptitForm(initial={'author': request.user}
...

Related

Failure to save certain attributes from ModelForm to django database (Logic error)

I have a ModelForm called ListingForm. It takes data from a user but I have stopped some of the model attributes from appearing in this form as I want to feed data to those myself. I have put print statements in my createlisting function in views.py to inspect if the data is actually being saved correctltly, it turns out the data is being saved. Here is the createlisting function:
def create_listing(request):
if request.method == 'POST':
import datetime
listing_form = ListingForm(request.POST, request.FILES)
if listing_form.is_valid():
bid = listing_form.cleaned_data['starting_bid']
print(bid)
listing_form.save(commit=False)
listing_form.user = request.user
print(listing_form.user)
listing_form.date_made = datetime.datetime.today()
listing_form.is_active = True
listing_form.category = Category.objects.get(name=listing_form.cleaned_data['listing_category'])
print(listing_form.category)
#The form is being saved correctly here, and the print statements give the correct results in my terminal
listing_form.save()
Bid.objects.create(user= request.user, value=bid, listing=listing_form.instance)
all_listings = Listing.objects.all()
return render(request, 'auctions/index.html', {
'all_listings': all_listings })
else:
listing_form = ListingForm()
return render(request, 'auctions/createlisting.html',{
'listing_form':listing_form
})
However, when I try to access the data from the model Listing from which the ListingForm is inheriting, the print statements I have put for debugging return the default values for certain fields (category and user) instead of the values I have saved in the ListingForm.
Here is the code that allows me to view the data for the model instance I have created. Mind you, all the other fields have saved correctly except for the fields category and user:
def view_listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
#the print results return the default values for the fields category and user instead of the values I saved in my ModelForm
print(listing.category)
print(listing.user)
if request.user == listing.user:
return render(request, 'auctions/view_listing.html', {
'listing': listing,
'flag':True,
'count': listing.bids.all().count()
})
else:
return render(request, 'auctions/view_listing.html',{
'listing':listing,
'count': listing.bids.all().count()
})
What could be the problem with my code?
Also, let me provide the code for some of my models and a form as the error might be embedded in those:
Listing Model:
class Listing(models.Model):
NAME_CHOICES = [
('Fashion', 'Fashion'),
('Toys','Toys'),
('Electronics','Electronics'),
('Home', 'Home'),
('Other', 'Other')
]
title = models.CharField(max_length= 64)
date_made = models.DateTimeField(auto_now_add=True)
description = models.TextField()
user = models.ForeignKey(User, to_field='username', on_delete=models.CASCADE, related_name='user_listings', null=True)
starting_bid = models.DecimalField(decimal_places=2, max_digits=264, default=10.00)
upload_image = models.ImageField(blank=True, upload_to='media/media')
category = models.ForeignKey(Category, on_delete=models.CASCADE, to_field='name', related_name='category_listings', default=NAME_CHOICES[4][0], db_constraint=False)
listing_category = models.CharField(max_length=12, choices=NAME_CHOICES, null=True, default=NAME_CHOICES[4][0])
is_active = models.BooleanField(default=True)
watchlist = models.ForeignKey('Watchlist', on_delete=models.DO_NOTHING, related_name='listings', null=True)
Category Model:
class Category(models.Model):
NAME_CHOICES = [
('Fashion', 'Fashion'),
('Toys','Toys'),
('Electronics','Electronics'),
('Home', 'Home'),
('Other', 'Other')
]
name = models.CharField(max_length=12, choices= NAME_CHOICES, unique=True)
User Model:
class User(AbstractUser):
def __str__(self):
return f'{self.username} '
ListingForm`` (ModelForm```):
class ListingForm(ModelForm):
class Meta:
model = Listing
exclude = [
'date_made',
'user',
'category',
'is_active',
'watchlist'
]
Any form of help would be greatly appreciated.
When you call listing_form.save(commit=False) it returns an unsaved model instance with the submitted values. If you assign that to a variable, you can use it to set the other field values and save:
def create_listing(request):
if request.method == 'POST':
import datetime
listing_form = ListingForm(request.POST, request.FILES)
if listing_form.is_valid():
bid = listing_form.cleaned_data['starting_bid']
listing = listing_form.save(commit=False)
listing.user = request.user
listing.date_made = datetime.datetime.today()
listing.is_active = True
listing.category = Category.objects.get(name=listing_form.cleaned_data['listing_category'])
listing.save()
Bid.objects.create(user=request.user, value=bid, listing=listing)
# You should probably use HttpResponseRedirect to an `all_listings` page, rather than displaying them here
all_listings = Listing.objects.all()
return render(request, 'auctions/index.html', {
'all_listings': all_listings })
Here's a link to the ModelForm.save() docs.

Django related model not updating on form submission

How do I update a non existing related object through Django model forms ?
I have two objects: Participant and Emergency. Emergency is a child of participant like if run the query: participant = ParticipantInfo.objects.get(pk = prk) I can access emergency = participant.emergency.
I cannot update emergency with data from a form using a POST request.
Can anyone help me please.
Thanks
Here's my models.py for clarity.
models.py
class EmergencyInfo(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
phone_number = models.CharField(max_length=50)
email = models.EmailField(max_length=100, blank=True, verbose_name="Emergency Contact Email")
relationship = models.CharField(max_length=100)
class ParticipantInfo(models.Model):
first_name = models.CharField(max_length=100)
middle_initial = models.CharField(max_length=1, blank=True)
emergency = models.ForeignKey(EmergencyInfo, on_delete = models.CASCADE, editable= False, null=True, blank=True)
views.py
def update_participant(request, pk):
# this function comes after update_specific
if request.method == "GET":
forms = get_participant_form_data(pk)
context = {'forms': forms, 'pk': pk}
return render(request, 'core/participantinfo_update_form.html', context)
if request.method == "POST":
return update_specific_form(request, pk)
def update_specific_form(request, pk):
participant = ParticipantInfo.objects.get(pk = pk)
# if the object didn't exist create it like normal
if participant.emergency is None:
emergencyform =EmergencyForm(request.POST)
if (emergencyform.is_valid):
emergencyform.save()
messages.success(request, 'saved')
return redirect(request.path_info)
# if the object exists, update it
if participant.emergency is not None:
emergencyform = EmergencyForm(request.POST, instance = participant.emergency)
if (emergencyform.is_valid):
emergencyform.save()
messages.success(request, 'saved')
return redirect(request.path_info)
Your problem seems to be with the is_valid method. Replace it with is_valid(). So your lines would be:
if (emergencyform.is_valid()):
#code
I have found an answer. Not only I needed to call the is_valid() instead of is_valid
but I also needed to tie the created object with it's parent like:
Save the new child object
Save the parent objects (updates the null
foreign key to a value)
*#get the existing parent object*
participant = ParticipantInfo.objects.get(pk = pk)
*#if no child object exists*
if participant.emergency is None:
emergencyform =EmergencyForm(request.POST)
if (emergencyform.is_valid()):
emergency = emergencyform.save(commit=False)
participant.emergency = emergency
emergencyform.save()
participant.save()
messages.success(request, 'saved')
return redirect(request.path_info)

Django Modelform - setting field value to foreign key

I created two models in my app: "Prescription" and "Prescription_status." When a user clicks save on the "New_prescription" modelform, I need to add a "Prescription_status" to the "Prescription."
For example, below I'd like to add 'Draft' status (PK=1). I don't want to set a default status. I've been trying everything, what am I missing?? Thanks in advance!
models.py
# Static Prescription Status Types
class Prescription_status(models.Model):
status = models.CharField(max_length=200)
status_definition = models.TextField()
def __str__(self):
return '%s' % (self.status)
# Prescription Model
class Prescription(models.Model):
order_id = models.AutoField(primary_key=True, unique=True)
status = models.ForeignKey(Prescription_status, models.SET_NULL, null=True)
I saved the following Prescription_status objects to the database, which I'd like to reference as users save or edit prescriptions:
status_id for "Draft" status = 1
status_id for "Ready for Signing" status = 2
status_id for "Signed and Authorized" status = 3
database chart showing PK for each status
forms.py
class PrescriptionForm(forms.ModelForm):
class Meta:
model = Prescription
fields = ('medication', 'quantity', 'directions', 'refills', 'earliest_permitted_fill_date', 'daw',)
widgets = {
'earliest_permitted_fill_date': DatePickerInput(), # default date-format %m/%d/%Y will be used
}
views.py
def new_rx(request):
if request.method == "POST":
form = PrescriptionForm(request.POST)
if form.is_valid():
prescription = form.save(commit=False)
prescription.status = Prescription_status.objects.get(pk=form.cleaned_data['1'])
prescription.save()
return redirect('home')
else:
form = PrescriptionForm()
return render(request, 'app/new_rx.html', {'form': form})
The above results in "NameError: name 'Prescription_status' is not defined." What is the right way to do this?

Django form intergrityerror: foreign key with unique field, unique constraint fails

When trying to add a second appointment (for the same date) which has a dayplan foreign key using ModelForm and CreateView, unique constraint fails due to DayPlan having 'date' field as unique.
This issue is not present using the django-admin create form.
I tried to remove the unique=True from dayplan.date to see what happens -> every time i add an appointment, even if dayplan.date exist, a new dayplan is created.
the issue seems to be related to these 2 line:
daydate = DayPlan.objects.filter(date=planned_date)
form.cleaned_data['dayplan'] = daydate
The code is here:
class DayPlan(models.Model):
date = models.DateField(unique=True, db_index=True)
comment = models.TextField(null=True, blank=True)
def __str__(self):
return 'Planning voor {}'.format(self.date)
def get_absolute_url(self):
return reverse('organizer_dayplan_detail', kwargs={'pk': self.pk})
class Appointment(models.Model):
comment = models.CharField(null=True, blank=True, max_length=255)
planned_date = models.DateField()
doctor = models.ForeignKey(Doctor)
visited = models.BooleanField(default=False)
dayplan = models.ForeignKey(DayPlan)
class AppointCreate(CreateView):
model = Appointment
form_class = AppointmentForm
template_name = 'organizer/organizer_appointment_create.html'
# initial = {'doctor': 'pk', 'comment': 'test',}
def get_initial(self):
return {
"doctor": self.request.GET.get('doctor')
}
def form_valid(self, form):
planned_date = form.cleaned_data['planned_date']
try:
daydate = DayPlan.objects.filter(date=planned_date)
form.cleaned_data['dayplan'] = daydate
form.instance.save()
except:
daydate = DayPlan.objects.create(date=planned_date)
form.instance.dayplan = daydate
form.instance.save()
return super(AppointCreate, self).form_valid(form)
class AppointmentForm(forms.ModelForm):
class Meta:
model = Appointment
fields = {'comment', 'planned_date', 'doctor', 'visited', 'dayplan'}
widgets = {'visited': forms.HiddenInput(),}
exclude = {'dayplan',}
P.S. i do realize that i don't need to use "form.instance.save()" here. removing them has no effect.
Thanks in advance!
solved
daydate, created = DayPlan.objects.get_or_create(date=planned_date)
form.instance.dayplan = DayPlan.objects.get(date=planned_date)

Django: Edit ModelForm using AutoField

I'm trying to make a view where the user can edit DB records through a form in a template. I've searched a lot of web pages (and Django docs as well) where they teach how to make these views, but they always use the "id" that Django generates for each Model. In this particular Model, I have to use an AutoField to override the "id". Is there a way to use this AutoField as an "id" of the record with Django?
Here's my complete model:
class T031003 (models.Model):
C003IDCD = AutoField(primary_key=True)
C003INST = models.IntegerField(unique=True) #usar AutoSlug
C003TPCD = models.CharField(max_length=1)
C003CHCD = models.CharField(max_length=14)
C003MTR = models.CharField(max_length=30, blank=True, null=True)
C003CTCD = models.CharField(max_length=3)
C003RZSC = models.CharField(max_length=60, blank=True, null=True)
C003EML = models.EmailField(max_length = 254, blank=True, null=True)
C003LOGA = models.CharField(max_length=20)
C003LOGB = models.DateTimeField()
C003LOGD = models.CharField(max_length=15, blank=True, null=True)
C003LOGF = models.CharField(max_length=20, blank=True, null=True)
def __unicode__(self):
return '%s' % self.C003MTR
class T031003Form(ModelForm):
class Meta:
model = T031003
ordering = ["-C003MTR"]
exclude = ('C003LOGA','C003LOGB','C003LOGD','C003LOGE','C003LOGF')
And here's the view I tried to do, but it gives me the error "No T031003 matches the given query." and it's right, since there is no "id" in the table:
def t031003form_edit(request, id=None):
pin = get_object_or_404(T031003, pk=id)
form = T031003Form(request.POST or None, instance=pin)
if request.method == 'POST':
if form.is_valid():
form = form.save(False)
form.C003LOGA = request.user
form.C003LOGB = datetime.date.today()
form.C003LOGD = request.META['REMOTE_ADDR']
form.C003LOGF = request.META['USERDOMAIN']
form.save()
form = T031003Form()
else:
return HttpResponseRedirect('/erro/')
return render_to_response('T031003Form_edit.html', {'form': form,}, context_instance=RequestContext(request))
Any help would be very appreciated!
If a model has an AutoField — an auto-incrementing primary key — then that auto-incremented value will be calculated and saved as an attribute on your object the first time you call save():
>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id # Returns None, because b doesn't have an ID yet.
>>> b2.save()
>>> b2.id # Returns the ID of your new object.
There's no way to tell what the value of an ID will be before you call save(), because that value is calculated by your database, not by Django.
ref : https://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs
Well, thanks to the help from a close friend, I could do the trick using formsets. Here's the view:
def t031002form_edit(request, id_auto):
j = get_object_or_404(T031002, pk=id_auto)
T031003FormSet = modelformset_factory(T031002, can_delete=True, max_num=1)
if request.method == 'POST':
form = T031002FormSet(request.POST or None, request.FILES or None, queryset=T031002.objects.filter(pk=id_auto))
if form.is_valid():
instance = form.save(commit=False)
form.C003LOGA = request.user
form.C003LOGB = datetime.date.today()
form.C003LOGD = request.META['REMOTE_ADDR']
form.C003LOGF = request.META['USERDOMAIN']
for reform in instance:
reform.save()
else:
return HttpResponseRedirect('/erro/')
else:
form = T031002FormSet(queryset=T031002.objects.filter(pk=id_auto))
return render_to_response(('T031002Form_edit.html'), {'form': form,}, context_instance=RequestContext(request))
So, with formsets, you can work nicely and with no worries. Hope it helps others with this same questioning.

Categories