I am trying to save an instance of a model but to no avail.
Below is my model;
class AudioFile(models.Model):
name = models.CharField(max_length=100,default='')
audio_file = models.FileField()
uploader = models.ForeignKey(User,default='')
def __unicode__(self):
return self.name
I have the below form;
class AudioFileForm(forms.ModelForm):
class Meta:
model = AudioFile
fields = ['name', 'audio_file']
def clean_audio_file(self):
audio = self.cleaned_data['audio_file']
if audio:
if audio._size > 5*1024*1024:
raise ValidationError("File too large ( > 5mb )")
if os.path.splitext(audio.name)[1] != ".mp3":
raise ValidationError("We only support mp3!")
return audio
else:
raise validationError("Couldn't read uploaded file")
And I have the below view to handle the submitted form;
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['uploader'] = request.user //view requires login
form.save()
return HttpResponseRedirect(
reverse('home_audio',kwargs={'pk':audio_file.pk})
)
else:
return HttpResponse(form.errors)
But on submission I get the error; IntegrityError at /uploadaudio
NOT NULL constraint failed: stationrunner_audiofile.uploader_id /uploadaudio is the URL correspoding to the view and stationrunner is my app's name.
Someone please help out.
Try changing the view:
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
audio_file = form.save(commit=False) // This will not hit the database, and no IntegrityError will be raised
audio_file.uploader = request.user // Tack on the user,
audio_file.save()
return HttpResponseRedirect(
reverse_lazy('home_audio',kwargs={'pk':audio_file.pk}) // Use reverse lazy to prevent circular import issues.
)
else:
return HttpResponse(form.errors)
Also you could fix some issues with the model:
from django.conf import settings
from django.db import models
class AudioFile(models.Model):
name = models.CharField(max_length=100) // If the field is not allowed to be blank, the default blank does not make sense.
audio_file = models.FileField(upload_to="audio_files") // Without this parameter file field does not work.
uploader = models.ForeignKey(settings.AUTH_USER_MODEL) // This should reference the user model declared in your settings file.
def __unicode__(self):
return self.name
Related
IntegrityError at /
UNIQUE constraint failed: pages_profile.username
Request Method: POST
Request URL: http://127.0.0.1:8000/
Django Version: 3.2.9
Exception Type: IntegrityError
Exception Value:
UNIQUE constraint failed: pages_profile.username
How would you update an Abstractuser's custom avatar field?
Specifically obj = Profile.objects.create(avatar = img)
from django.shortcuts import redirect, render
from .forms import UserProfileForm
from .models import Profile
def index(request):
context = {}
if request.method == "POST":
form = UserProfileForm(request.POST, request.FILES)
if form.is_valid():
img = form.cleaned_data.get("avatar")
obj = Profile.objects.create(
avatar = img
)
obj.save()
print(obj)
return redirect(request, "home.html", obj)
else:
form = UserProfileForm()
context['form']= form
return render(request, "home.html", context)
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class Profile(AbstractUser):
""" bio = models.TextField(max_length=500, blank=True)
phone_number = models.CharField(max_length=12, blank=True)
birth_date = models.DateField(null=True, blank=True) """
avatar = models.ImageField(default='default.png', upload_to='', null=True, blank=True)
forms.py
from django import forms
from django.core.files.images import get_image_dimensions
from pages.models import Profile
class UserProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('avatar',)
def clean_avatar(self):
avatar = self.cleaned_data['avatar']
try:
w, h = get_image_dimensions(avatar)
#validate dimensions
max_width = max_height = 1000
if w > max_width or h > max_height:
raise forms.ValidationError(
u'Please use an image that is '
'%s x %s pixels or smaller.' % (max_width, max_height))
#validate content type
main, sub = avatar.content_type.split('/')
if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
raise forms.ValidationError(u'Please use a JPEG, '
'GIF or PNG image.')
#validate file size
if len(avatar) > (20 * 1024):
raise forms.ValidationError(
u'Avatar file size may not exceed 20k.')
except AttributeError:
"""
Handles case when we are updating the user profile
and do not supply a new avatar
"""
pass
return avatar
The error
IntegrityError at /
UNIQUE constraint failed: pages_profile.username
is implying that there is already another profile object with the same username that you are trying to create.
To fix this you need to update the existing profile if it already exists.
You can use django's create_or_update like so
obj, created = Profile.objects.update_or_create(
username=form.cleaned_data.get('username'),
defaults={'avatar': img},
)
this will make django update any existing Profile object with username=form.cleaned_data.get('username')
if such a profile object does not exist, then it will be created.
This is what I got
IntegrityError at /malex/upload/
NOT NULL constraint failed: malex_document.uploaded_by_id
Request Method: POST
Request URL: http://127.0.0.1:8000/malex/upload/
Django Version: 2.0.5
Exception Type: IntegrityError
Models
class Profile(models.Model):
username = models.OneToOneField(User, on_delete=models.CASCADE)
password = models.TextField(max_length=80,blank=True)
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
uploaded_by = models.ForeignKey(Profile,on_delete=models.CASCADE)
date_uploaded = models.DateTimeField(auto_now_add=True)
Forms
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
class DocumentForm(forms.Form):
docfile = forms.FileField(label='Select a file')
views
def upload(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
**newdoc.uploaded_by = request.user.profile**
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('upload'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(request,'upload.html',{'documents': documents, 'form': form})
If I add the line as neverwalker alone has suggested
'AnonymousUser' object has no attribute 'profile'
What even makes things more strange with this integrity error is that the file is uploaded
~/nup/malex/media/documents/2018/06/22$ ls -lh 262_V01_C06_R000_TEy_BH_131072H.ats
-rw------- 1 milenko milenko 46M јун 22 07:22 262_V01_C06_R000_TEy_BH_131072H.ats
Why do I got this error and how to fix this?
You didn't set uploaded_by attribute. Since it's not nullable this is raise error. To fix this, you need to provide uploaded_by to new Document instance before saving like this:
#login_required
def upload(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.uploaded_by = request.user.profile # if Profile has onetofield with User model
# newdoc.uploaded_by = request.user if Profile is your user_model
newdoc.save()
Note uose login_required decorator to ensure current user is authenticated.
Also you can set uploaded_by as nullable field:
uploaded_by = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)
In this case uploaded_by will not required, and will be set as ULL for new records.
I am trying to save the data in database using Python-Django. But i am getting this error:
'userInfo' object has no attribute 'suggestion'
This is my model.py file
model.py
class userInfo(models.Model):
#user = models.ForeignKey(User)
#age = models.IntegerField()
u_name=models.TextField("Name", null = True, blank = True)
u_address=models.TextField("Address", null = True, blank = True)
def __unicode__(self):
return self.u_name
This is my view.py file
view.py
def gaurav(request):
print request
form=userInfoForm()
if request.POST:
form = userInfoForm(request.POST)
anw=form.save(commit=False)
anw.user=request.user
anw.save()
form= userInfoForm(request.POST)
if form.is_valid():
user1=form.save()
return render(request, 'userview/home.html', {'form': form})
This is my form.py file
form.py
class userInfoForm(forms.ModelForm):
class Meta:
model = userInfo
def __init__(self, *args, **kwargs):
super(userInfoForm,self).__init__()
Inside the__unicode__ method of userInfo, you are trying to use self.suggestion but suggestion is not defined in the model fields.
Try using another attribute:
class userInfo(models.Model):
# Model fields..
def __unicode__(self):
return self.u_name
If you have changed the code as #Sunny Nanda Mentioned and still getting the same error, then try cleaning the .pyc files of that project and reload the dev server
my question is about modelforms, models and instances. After doing some troubleshooting I think my problem is that either the user field from UserFile doesn't associate itself to the auth.User or that the modelform doesn't pass the instance of auth.User. The error is at the dynamic pathing - file_destination - when I try self.user it can't find the user :/
# Model
class UserFile(models.Model):
user = models.ForeignKey('auth.User', related_name='user_file', primary_key=True, unique=True)
user_file = models.FileField(upload_to=file_destination, null=True)
def __unicode__(self):
return self.user_file.name
# View
def login_index(request):
template = 'loginIndex.html'
context = Context()
if request.user.is_authenticated():
if request.method == 'POST':
form = UserUpload(request.POST, request.FILES, instance=request.user)
context.update({'form': form})
if form.is_valid() and form.is_multipart():
instance = UserFile(user_file=request.FILES.get('user_file'))
instance.save()
else:
form = UserUpload()
context.update({'form': form})
return render(request, template, context)
else:
return render(request, template, context)
# Form
class UserUpload(ModelForm):
user_file = forms.FileField(required=False, widget=forms.ClearableFileInput, label='Upload')
class Meta:
model = UserFile
fields = ['user_file']
def clean_user_file(self):
check_user_file = self.cleaned_data.get('user_file')
if check_user_file:
if check_user_file.size > 5120000:
raise ValueError('File is too big for upload')
return check_user_file
# The problem arises when I submit the instance, which saves the file from the form to upload_to=file_destination
# In file_destination I get an error on self.user.username saying || DoesNotExist at "" UserFile has no user.
# My self.user is an None object.
def file_destination(self, filename):
filename = name_generator()
url = "%s/%s/%s" % (self.user.username, 'uploads' ,filename)
return url
You need to manually set the user field on your UserFile instance:
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instanve.save()
form.save_m2m() # add this if you add m2m relationships to `UserFile`
Also, it is a good idea to redirect after the form handling succeeds:
from django.shortcuts import redirect
# ...
return redirect("view-name")
I have a ModelForm:
class UploadForm(forms.ModelForm):
class Meta:
model = Image
fields = ['image']
which is based on model Image
class Image(models.Model):
def content_file_name(instance, filename):
return filename
name = models.CharField(max_length=50)
image = models.ImageField(upload_to=content_file_name)
user = models.ForeignKey(MyUser, related_name='image')
In views.py, I try to save the image name and user object (from session) along with the uploaded image to database.
form1 = UploadForm(request.POST, request.FILES)
if form1.is_valid():
image = request.FILES['image'] # image is of UploadedFile class
form1.Meta.model.name = image.name
form1.Meta.model.user = get_object_or_404(MyUser,username=request.session['user'])
form1.save()
return render(request, '16_upload01.html', context)
Problem is only the uploaded image gets saved. Error message in browser:
IntegrityError at /competition-big/big1/upload
comp_app_image.user_id may not be NULL
I confirmed this by checking on SQL command:
INSERT INTO "comp_app_image" ("name", "image", "user_id") VALUES ('', 'grey-160-100_1.png', None)
I figure that image name and user are not bounded to form1. But how can I achieve that?
EDIT
After some digging, I know I messed up with above code. Now I changed my code to this:
if form1.is_valid():
form1.cleaned_data['user'] = get_object_or_404(MyUser, username=request.session['user'])
form1.save()
But I still get null user_id error.
EDIT 2
Thanks Jacinda. Now I get this cleaner code:
if form1.is_valid():
form1.cleaned_data['user'] = request.user
form1.save()
But error null user_id remains.
If this form can only be accessed by a logged in user, use the login_required decorator, and you should always redirect after a POST. You should also read this section in the ModelForms documentation; which describes how to properly use a model form that has limited fields.
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
#login_required
def your_view(request):
form1 = UploadForm(request.POST, request.FILES)
if form1.is_valid():
image = request.FILES['image'] # image is of UploadedFile class
obj = form1.save(commit=False)
obj.name = image.name
obj.user = request.user
obj.save()
return redirect('your-view-name')
else:
return render(request, 'form.html', {'form': form1})
I think your issue is probably this line:
form1.Meta.model.user = get_object_or_404(MyUser,username=request.session['user'])
When I try and use your syntax (using the Django default django.contrib.auth) I get a KeyError on 'user'.
What I've always done when I need information about the user associated with a request is this:
username = request.user.username
Reference: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user
Of course, this will only work if your users are required to be logged in to upload images.