how can users upload file into Django model? - django

With these codes, I want each user to be able to upload their own file in their own model
forms.py:
class sp_UserNewOrderForm(forms.Form):
file= forms.FileField()
models.py:
class sp_Order(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.owner.username
class sp_OrderDetail(models.Model):
order = models.ForeignKey(sp_Order, on_delete=models.CASCADE)
file= models.FileField()
def __str__(self):
return self.order.owner.username
views.py:
#login_required
def add_user_order(request):
new_order_form = sp_UserNewOrderForm(request.POST or None)
if new_order_form.is_valid():
order = sp_Order.objects.filter(owner_id=request.user.id).first()
if order is None:
order = sp_Order.objects.create(owner_id=request.user.id)
file= new_order_form.cleaned_data.get('file')
order.sp_orderdetail_set.create(file=file)
# todo: redirect user to user panel
# return redirect('/user/orders')
return redirect('/')
return redirect('/')
HTML:
<form method="post" action="/add_sp">
{% csrf_token %}
{{ form.count }}
<button type="submit" class="btn btn-primary container">
upload
</button>
</form>
But these codes do not create the model. what is the problem?

The problem appears to be in this line:
order = sp_Order.objects.filter(owner_id=request.user.id).first()
I think you should replace owner_id = request.user.id with owner = request.user
owner_id is not an attribute of the model you're trying to filter or create

You need to include request.FILES when instantiating the form for the POST request.
def add_user_order(request):
if request.method == 'POST':
new_order_form = sp_UserNewOrderForm(request.POST, request.FILES)
if new_order_form.is_valid():
order = sp_Order.objects.filter(owner_id=request.user.id).first()
if order is None:
order = sp_Order.objects.create(owner_id=request.user.id)
file= new_order_form.cleaned_data.get('file')
order.sp_orderdetail_set.create(file=file)
# todo: redirect user to user panel
# return redirect('/user/orders')
return redirect('/')

Related

how to delete previous uploaded file when a new one gets uploaded using id

I have simple cv upload class for users to upload their resume. it works just fine but when they upload a newer one, the previous wont get deleted.
this is my code:
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
cvfile = models.FileField(upload_to="documents", null=True, validators= [validate_file_extension])
#property
def filename(self):
return os.path.basename(self.cvfile.name)
how can I reach the previous id? id = self.id - 1. something like that.
this is my views:
#login_required
def pdf_resume(request):
if request.method == 'POST':
form = DocumentForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('pdf_resume')
if 'delete' in request.GET:
return delete_item(ResumeDocument, request.GET['id'])
else:
form = DocumentForm()
documents = ResumeDocument.objects.filter(user=request.user)
if documents:
form = DocumentForm(instance=documents[0])
context = {
'form':form,
'documents':documents,
}
return render(request, 'reg/pdf_resume.html', context)
and this is also my HTML code:
<form id="document-form" method="POST" enctype="multipart/form-data" action="{% url 'pdf_resume' %}" autocomplete="off" class="ant-form ant-form-horizontal">
{% csrf_token %}
<p>{{ form }}</p>
<div class="ant-row-flex" style="margin-left: -10px; margin-right: -10px;"></div>
<button id="btn_submit" type="submit"
class="ant-btn ant-btn-primary"
ant-click-animating-without-extra-node="false" style="float: left;"><span>upload</span></button>
</form>
One possible solution is to save all uploaded CVs for each user and track the last uploaded CV with field uploaded_on. You may refer to the below high-level example:
class CVFile(models.Model):
file_name = models.CharField(max_length=200)
cv_file = models.FileField(upload_to="documents", null=True, validators=[validate_file_extension])
uploaded_on = models.DateTimeField(default=timezone.now, blank=True)
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
cv_file = models.ForeignKey(CVFile, on_delete=models.CASCADE)
You will need to amend your HMTL and views.py accordingly.
models.py
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
cvfile = models.FileField(upload_to="documents", null=True, validators=
[validate_file_extension])
views.py(i just look is there any resumedocuments for that user if yes so i give him
the form just if he was editing the existing file)
#login_required
def pdf_resume(request):
if request.method == 'POST':
form = DocumentForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('pdf_resume')
if 'delete' in request.GET:
return delete_item(ResumeDocument, request.GET['id'])
else:
form = DocumentForm()
documents = ResumeDocument.objects.filter(user=request.user)
if documents:#new
form = DocumentForm(instance=documents[0])
context = {
'form':form,
'documents':documents,
}
return render(request, 'reg/pdf_resume.html', context)
now inside your pdf_resume.html your can just pass the 'form' because you already check if that user has a document or not.

Why Django doesn't update an image field

I want to build a view that allows the user to update his profile picture.
Now in my view the cleaned data returns the current profile image path which then overwrites the existing one one by one. I'm not sure where the issue is.
Also since I use a default image within the model manager, I only want to delete the current imagefield if it isn't the default one.
# View
#require_POST
def update_profile_image(request, username):
"""
Updates the user profile
"""
form = ImageUpdateForm(request.POST)
if form.is_valid():
image = form.cleaned_data['profile_image']
print('image ' + str(image))
user = Account.objects.get(username=request.user.username)
user.profile_image = image
user.save()
return redirect('pollboard')
# Model
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=40, unique=True)
profile_image = models.ImageField(max_length=255, upload_to=get_profile_image_filepath, null=True, blank=True, default=get_default_profile_image())
# Custom Manager
class MyAccountManager(BaseUserManager):
def get_profile_image_filepath(self, filename):
return f'profile_image/{self.pk}/{"profile_image.png"}'
def get_default_profile_image():
return "profile_image/Logo_large.png"
# Form
class ImageUpdateForm(forms.ModelForm):
class Meta:
model = Account
fields = ['profile_image']
# Template
<div class="profile-image-modal">
<form method="post" action="update_profile_image/">
{% csrf_token %}
{{ profile_image_form }}
<button type="submit">Save Image</button>
</form>
</div>
You need to pass both request.POST and request.FILES to the form:
#require_POST
def update_profile_image(request, username):
"""
Updates the user profile
"""
# pass request.FILES as well &downarrow;
form = ImageUpdateForm(request.POST, request.FILES)
if form.is_valid():
image = form.cleaned_data['profile_image']
print('image ' + str(image))
user = Account.objects.get(username=request.user.username)
user.profile_image = image
user.save()
return redirect('pollboard')
furthermore you should set the encytpe=… [dev-mozilla] of the form to multipart/form-data to encode the file:
<form method="post" enctype="multipart/form-data" action="update_profile_image/">
{% csrf_token %}
{{ profile_image_form }}
<button type="submit">Save Image</button>
</form>

ModelForm in Django not saving anything

I am making a twitter clone app in Django. I have a model, and a modelform as so:
Class Tweet(models.Model):
content = models.TextField(blank=True, null=True)
image = models.FileField(upload_to='images/', blank=True, null=True)
class TweetForm(forms.ModelForm):
class Meta:
model = Tweet
fields = ['content',]
def clean_content(self):
content = self.cleaned_data.get('content')
if len(content) > MAX_TWEET_LENGTH:
raise forms.ValidationError('This tweet is too long')
I have a view for this:
def tweet_create_view(request, *args, **kwargs):
if request.method == 'POST':
form = TweetForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
form = TweetForm()
context = {
'form': form
}
return render(request, 'components/form.html', context)
and the template:
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-secondary" type="submit">Save</button>
</form>
When I submit the form data, in the database the value is shown as NULL, even if I pass in some text. What am I doing wrong??
You are not returning the cleaned form data from the clean function, as your clean function doesn't return anything if it passes the validation, it saves None/Null to DB.
def clean_content(self):
content = self.cleaned_data.get('content')
if len(content) > MAX_TWEET_LENGTH:
raise forms.ValidationError('This tweet is too long')
return content

Django Error: user_register_model matching query does not exist

How to fix This Error I'm Trying To Fix This Error But I Get Again And Again
i want to detect user who fill the form for example test fill the form but when i write the code down below i get this error
Any Help Will Be Appreciated!
ERROR
user_register_model matching query does not exist.
ERROR SCREENSHOT
Here is my Views.py
def buy_form(request):
if request.method == 'POST':
usr_buy = user_buy_form(request.POST)
if usr_buy.is_valid():
usr_buys = usr_buy.save(commit=False)
user_register_obj = user_register_model.objects.get(user=request.user)
usr_buys.users = user_register_obj
usr_buys.save()
else:
return print(usr_buy.errors)
else:
usr_buy = user_buy_form()
context = {'usr_buy':usr_buy}
return render(request,'user_buy.html',context)
Here is my Models.py
class user_register_model(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
join_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.user.username
class user_buy(models.Model):
users = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=200)
payment_method = models.CharField(max_length=500)
price = models.IntegerField()
Trade_limits = models.IntegerField()
Location = models.CharField(max_length=1000)
def __str__(self):
return self.users.user.username
Here is my Forms.py
class user_buy_form(forms.ModelForm):
class Meta():
model = user_buy
fields = '__all__'
exclude = ('users',)
Here is my user_buy.html
{% extends 'base.html' %}
{% block body_block %}
<form class="form-control" method="POST">
{% csrf_token %}
{{usr_buy.as_p}}
<input type="submit" class="btn btn-primary" value="Submit">
</form>
{% endblock %}
I didn't see any points here to create the user_register_model.If you are trying to add the currently logged in user you can do this:
request.user will give you the currently logged in user so for this the user must be logged in.
#login_required
def buy_form(request):
if request.method == 'POST':
usr_buy = user_buy_form(request.POST)
if usr_buy.is_valid():
usr_buys = usr_buy.save(commit=False)
usr_buys.users = request.user
usr_buys.save()
return redirect('some_path') # redirect to some path after saving the form
Class names should normally use the CapWords convention.
I think the request.user is not present in the user_register_model model thats why it is giving matching query doesnot exist error, first create it in the user_register_model and then query it.

Storing form data in the database

I can't figure out how to store a simple form in the database. I think I'm quite close but there is probably something wrong in my views.py. Here is my code, any ideas what I'm doing wrong? (also on dpaste)
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(forms.Form):
name = forms.CharField(max_length=30)
# views.py
#login_required
def newCategory(request):
if request.method == 'POST':
username = request.user.username
cform = CategoryForm(request.POST)
if cform.is_valid():
formInstance = cform.save(commit = False)
formInstance.user = username
formInstance.name = cform.cleaned_data['name']
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
formInstance.save()
# return HttpResponseRedirect('new-category/')
else:
form = CategoryForm()
context = {'form': form}
return render_to_response('new-category.html', context, context_instance=RequestContext(request))
# new-category.html
<h3>Insert New Category</h3>
<form action="/" method="post" id="food-form">{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="foodForm" value="Save" />
</form>
The line below is not useful at it current position. That command will perform a database query and assign the result as a queryset, before you have saved the form data.
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
This should work:
With cform as a normal Form:
if cform.is_valid():
formInstance = IngredienceCategory(user=request.user, cform.cleaned_data['name'])
formInstance.save()
If cform had been a ModelForm you could do:
if cform.is_valid():
formInstance = cform.save(commit=False)
formInstance.user = request.user
formInstance.save()
I do recommend you to check out ModelForms since it will build the cleaning functionality based on your model.
You should inherit from ModelForm
from django.forms import ModelForm
class CategoryForm(ModelForm):
class Meta:
model = IngredienceCategory
Refer to https://docs.djangoproject.com/en/dev/topics/forms/modelforms/ for how to render form and save it to database.