How to get the FileField from ModelFrom in django views - python

I currently want to send some data to my database by doing the following: Sending a document to the database and each document has a foreign key from the user table i.e. each document is a reference to an author(from another table) but it will be bad for the user to get all the users in the system and choosing one of them, I want the author assignment to be performed in the views. So as a summary I want to get fields from the form in views. I found a corresponding question and tip at this link, but the only issue here being that a file was not inlcuded in his model but on mine yes. Snipets of my files below;
models.py
class UploadedDocuments(models.Model):
user = models.ForeignKey(
TheUsers,
on_delete=models.CASCADE,
)
document = models.FileField(
verbose_name='Document',
upload_to=f'documents/%Y/',
null=True,
)
plagiarism_status = models.CharField(max_length=100, null=True)
serialised_content = models.CharField(null=True, max_length=255)
date_uploaded = models.DateTimeField(
verbose_name='Uploaded On',
auto_now_add=True
)
def __str__(self):
return self.document.name
class Meta:
verbose_name = "Document"
verbose_name_plural = 'Documents'
Views.py
def upload(request):
form = UploadedDocumentsForm(request.POST, request.FILES)
if request.POST:
if form.is_valid():
form_stack = form.save(commit = False)
form.user = request.user
form_stack.serialised_content = "bala"
form_stack.plagiarism_status = 'Hello'
form_stack.save()
return redirect("results")
function which is constantly telling me invalid.
forms.py
class UploadedDocumentsForm(forms.ModelForm):
class Meta:
model = UploadedDocuments
fields = ['document', 'user', 'plagiarism_status', 'serialised_content']
widgets = {
'document': forms.FileInput(
attrs = {
'class': 'drop-zone__input',
'id': 'file',
'accept': '.doc, .docx, .txt',
'required': True,
}
),
'user': forms.Select(
attrs = {
}
),
'plagiarism_status': forms.TextInput(
attrs = {
'hidden': True,
}
),
'serialised_content': forms.TextInput(
attrs = {
'hidden': True,
}
)
}
my template file
<form action="{% url 'upload' %}" method="POST" enctype='multipart/form-data'>
{% csrf_token %}
<div class="drop-zone w-50">
<span class="drop-zone__prompt text-center h3">
Drops file here
</span>
{{ form.document }}
{{ form.user }}
{{ form.serialised_content }}
{{ form.plagiarism_status }}
</div>
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-white btn-outline-success
p-4 px-5 w-lg-25 w-md-50 w-sm-50 text-capitalize5 my-5">
<i class="fa fa-2x fa-sync px-3"></i>
Upload
</button>
</div>
</form>
Any suggestion on how this could be done will be helpful.

add blank and none to your user of UploadedDocuments model:
class UploadedDocuments(models.Model):
user = models.ForeignKey(
TheUsers,
null=True,
blank=True,
default=None,
on_delete=models.CASCADE,
)
...

Related

Display the data of User role in Django Template

I have a django model with User roles. I want to be able to get the first_name, last_name and other details of a user role displayed other a template when another user role or the same user role is logged in.
This is my models
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
#username = models.CharField(unique = False , max_length=100)
#email = models.CharField(unique = True , max_length=100 )
nin = models.IntegerField(unique = False , null=True)
avatar = models.ImageField(null= True, default="avatar.svg")
is_landlord = models.BooleanField(default=False)
objects = UserManager()
REQUIRED_FIELDS= []
class Landlord(models.Model):
user = models.OneToOneField(User,related_name="prop_owner", null= True, on_delete=models.CASCADE)
bio = models.TextField(null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS= []
objects = UserManager()
def __str__(self):
return str(self.user)
This is my views
def propertySingle(
request,
pk,
is_landlord,
):
user = User.objects.get(is_landlord=is_landlord)
property = Property.objects.get(id=pk)
properties = Property.objects.all()
images = Image.objects.filter(property=property)
context = {
"property": property,
"properties": properties,
"images": images,
'user':user,
}
return render(request, "base/page-listing-single.html", context)
Template
<div class="sl_creator">
<h4 class="mb25">Property Owned By:</h4>
<div class="media">
<img class="mr-3" style="width: 90px; height:90px;" src="{{request.user.avatar.url}}" alt="avatar">
<div class="media-body">
<h5 class="mt-0 mb0">{{user.last_name}} {{request.user.first_name}}</h5>
<a class="text-thm" href="#">View other Listings by {{property.landlord.last_name}} {{property.user.is_landlord.first_name}}
You can do all this in the template if all you are testing for if the current user is a landlord, because you can always refer to the request.user User instance to see who is accessing the page.
<h4 class="mb25">Property Owned By:</h4>
{% if request.user.is_landlord %}
...#show landlord details
{% else %}
This information only available to landlords
However, you have a problem in your view. You are using get (returns one record) to get all the users who have is_landlord = True (which will be many). This will give you an error. Also, you may get confused about which user you are referring to in your template as there ius already a rquest user in your tempalte by default. Try something like this
def propertySingle(
request,
pk,
):
# get the property and all info about the landlord
#now in the template we can access property.landlord with no extra db calls
property = Property.objects.get(id=pk).select_related('landlord')
properties = Property.objects.all()
images = Image.objects.filter(property=property)
context = {
"property": property,
"properties": properties,
"images": images,
}
return render(request, "base/page-listing-single.html", context)
Now in your template you can do the following
Template
<div class="sl_creator">
<h4 class="mb25">Property Owned By:</h4>
{% if request.user == property.landlord %}
<!-- the user is THE landlord for this property -->
You: {{request. user.last_name}}, {{request.user.first_name}}
{% endif %}
{% if request.user.is_landlord %}
<!-- the user is A landlord, but not necessarily for this property -->
<div class="media">
<img class="mr-3" style="width: 90px; height:90px;" src="{{property.landlord.avatar.url}}" alt="avatar">
<div class="media-body">
<a class="text-thm" href="#">View other Listings by {{property.landlord.last_name}} {{property.landlord.first_name}}
</div>
</div>
{% else %}
<div class="media-body">
This information only available to landlords
</div>
{%end if %}

how to correctly saving a profile instance in django

I have a problem with creating a profile instance in Django. when I try to update a profile the images of the profile don't save in the database My guess is that the form.save(commit=False) does not upload the photo nor update the field as it should but I do not understand why :
here is my code:
models.py
class Profile(models.Model):
user = models.OneToOneField(User, primary_key =True, on_delete=models.CASCADE, related_name= 'profile')
image = models.OneToOneField(UserImage, on_delete=models.SET_NULL, null=True, blank=True)
phone_number = models.CharField(max_length=50, null = True, blank = True)
followers = models.ManyToManyField(User, related_name='follower', blank=True)
following = models.ManyToManyField(User, related_name='following', blank=True)
biography = models.TextField(max_length=250, null=True, blank=True)
class UserImage(models.Model):
avatar = models.ImageField(blank=True, null=True,upload_to='avatar_pic')
header_image = models.ImageField(blank=True, null=True,upload_to='header_pic')
forms.py
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = (
'phone_number',
'biography',
)
class ImageProfileForm(ModelForm):
class Meta:
model = UserImage
fields = (
'avatar',
'header_image',
)
views.py
#login_required
def CompleteSignUp(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST,request.FILES ,instance=request.user.profile)
image_profile_form = ImageProfileForm(request.POST, instance=request.user.profile.image)
if profile_form.is_valid() and image_profile_form.is_valid():
profile = profile_form.save(commit=False)
images = image_profile_form.save()
profile.user = request.user
profile.social = social
profile.image = images
profile_form.save()
return redirect('blog:Home')
else:
profile_form = ProfileForm(
initial={
'phone_number':request.user.profile.phone_number,
'biography':request.user.profile.biography
}
)
if request.user.profile.image:
image_profile_form = ImageProfileForm(
initial={
'avatar':request.user.profile.image.avatar,
'header_image':request.user.profile.image.header_image
}
)
else:
image_profile_form = ImageProfileForm()
return render(request, 'user/createprofile.html', {'form_p': profile_form, 'form_i': image_profile_form})
templates
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form_p.biography }}
biography
</div>
<div>
{{ form_p.phone_number }}
phone_number
</div>
<div>
{{ form_i.avatar }}
avatar
</div>
<div>
{{ form_i.header_image }}
header
</div>
<br>
<input type="submit" value="Register">
</br>
</form>
{% for field in form_s %}
{% for error in field.errors %}
<p style="color: rgba(255, 0, 0, 0.678)">{{ error }}</p>
{% endfor %}
{% endfor %}
{% endblock %}
profile save but the image of the profile doesn't save what's my fault.
...
Change:
profile.user = request.user
profile.social = social
profile.image = images
profile_form.save()
To:
profile.user = request.user
profile.social = social
profile.image = images
profile.save() # Use this
You need to save profile instead of the form with commit=False, because you did custom stuff to profile.

How to use foreign key value to pre-populate another form field in Django

I have two models in for, one has member details and the other is the user model, what i want is to use the foreign key of member model in User model when creating a member account.
In a form, when a member name with foreign key is selected, the email field should be pre-populated with value from the members table.
I know ajax can do this asynchronous call to the database but how do i achieve this? thank you.
User Model
class User(AbstractBaseUser , PermissionsMixin):
email = models.EmailField(max_length=255, unique=True, blank=True, null=True)
username = models.CharField(max_length=30, unique=True)
Role = models.CharField(max_length=250, choices=roles, blank=True, null=True)
full_name = models.ForeignKey('Members', on_delete=models.SET_NULL, max_length=100, null=True, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
Is_View_on_Web = models.CharField(max_length=20, default='Yes', choices=OPTIONS,null=True,blank=True)
USERNAME_FIELD = 'username'
REQUIRED_FILEDS = []
objects = UserManager()
published = PublishedStatusManager()
def __str__(self):
return str(self.full_name)
and Members Model
class Members(models.Model):
First_Name=models.CharField(max_length=100,null=True)
Second_Name=models.CharField(max_length=100,null=True)
Home_Cell=models.CharField(max_length=100, choices=cell,null=True)
Residence=models.CharField(max_length=100,null=True)
Telephone=models.CharField(max_length=100,null=True)
Email=models.CharField(max_length=100,null=True, blank=True)
def __str__(self):
return str(self.First_Name )+ ' ' + str(self.Second_Name)
here is my register.html
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom">Add New User to the System</legend>
<div class="separator"></div>
<div class="form-group">
{{ form|crispy}}
</div>
</fieldset>
<div class="form-group">
<button class="btn btn-primary" type="submit"> Submit</button>
</div>
</form>
form.py
class RegisterForm(forms.ModelForm):
class Meta:
model = User
fields = ['full_name','email','username','Role','Is_View_on_Web']
this is my proposition after test and it works fine:
form.py => add attribut that will call a JS function defined in your .html
from django.forms import ModelForm, Form
from .models import User
class RegisterForm(ModelForm):
class Meta:
model = User
fields = ['username', 'full_name', 'email', 'Role', 'Is_View_on_Web']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['full_name'].widget.attrs['onchange'] = "load_email()"
.html: => define the JS function
<body>
<form id = "myform" method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom">Add New User to the System</legend>
<div class="separator"></div>
<div class="form-group">
{{ form }}
</div>
</fieldset>
<div class="form-group">
<button class="btn btn-primary" type="submit"> Submit</button>
</div>
</form>
</body>
<script>
function load_email()
{
document.getElementById('myform').action = "/stack/myview";
document.getElementById("myform").submit();
}
</script>
Views.py:=> new view that will look for the email address in the database and return to the template
def myview(request):
form = RegisterForm(request.POST)
if form.is_valid():
db = form.save(commit=False)
db.email = Members.objects.get(id__exact=form['full_name'].value()).Email
form = RegisterForm(instance=db)
content = {'form': form}
return render(request, 'stack/index.html', content)
else:
content = {'form': form}
return render(request, 'stack/index.html', content)

Django save only first form of formset

I've looked through every similar question (and tried them), but still couldn't find answer.
I have two models:
class Project(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
name = models.CharField(max_length=120, verbose_name = "Название проекта")
url = models.URLField(max_length=120, unique=True, verbose_name = "Полный адрес сайта")
robots_length = models.CharField(max_length=5, default=0)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.name
def __str__(self):
return self.name
def get_absolute_url(self):
from django.urls import reverse
return reverse('projects:detail', args=[str(self.id)])
class ProjectPage(models.Model):
page_project = models.ForeignKey(Project, on_delete=models.CASCADE)
page_url = models.URLField(verbose_name = "Адрес страницы")
page_title = models.CharField(max_length=300, blank=True, verbose_name = "meta-title",default="")
page_description = models.CharField(max_length=300, blank=True, verbose_name = "meta-description",default="")
page_h1 = models.CharField(max_length=300, blank=True, verbose_name = "Заголовок h1",default="")
def __unicode__(self):
return self.page_url
def __str__(self):
return self.page_url
For each model there is a form:
class ProjectFormUpdate(forms.ModelForm):
class Meta:
model = Project
fields = [
"name",
"url",
]
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Произвольное название'}),
}
class ProjectPageForm(forms.ModelForm):
class Meta:
model = ProjectPage
fields = [
'page_project',
'page_url',
'page_title',
'page_description',
'page_h1',
]
widgets = {
'page_project': forms.HiddenInput()
}
In views.py I have:
def projects_update(request, proj=None):
instance = get_object_or_404(Project, id=proj)
form = ProjectFormUpdate(request.POST or None, instance=instance)
formset_f = modelformset_factory(ProjectPage, form=ProjectPageForm, extra=3)
formset = formset_f(queryset=ProjectPage.objects.filter(page_project__id=proj), initial =[{'page_project': proj}])
if request.method == 'POST':
formset = formset_f(request.POST)
for formset_form in formset:
if formset_form.is_valid() and formset_form.has_changed():
formset_form.save()
if form.is_valid():
form.save()
context = {
'title': "Редактируем проект - "+instance.name,
'form': form,
'formset': formset,
'instance': instance,
}
return render(request, "projects_update.html", context)
And, finaly, html
<form method="POST" action="" class="create-form">
{{ formset.management_form }}
{% csrf_token %}
<div class="row">
<div class="col-lg-6 offset-lg-3 col-md-10 offset-md-1 col-xs-10 offset-xs-1 form-bg">
<h2>Общие данные</h2>
{{ form|crispy}}
<input type="submit" class="btn btn-success" value="Обновить проект" />
</div>
</div>
{% for formset_form in formset %}
<div class="row form-container">
<div class="col-lg-6 offset-lg-3 col-md-10 offset-md-1 col-xs-10 offset-xs-1 form-bg">
<h3>Страница {{forloop.counter}}</h3>
{{ formset_form|crispy}}
</div>
</div>
{% endfor %}
</form>
What I am trying to achieve is: when user enters a page, he gets a form with project name and project URL already filled in. So, he can correct them.
Below, I want to show a filled in form for every page allready created for this project and several empty forms for creating new.
What happens is all initial data is displayed correctly, but when I fill several empty forms - only first empty form is saved each time.
Here is how it was solved:
Included errors properly.
Saw that second to last form lack required field (hiddenInput)
Made changes in view so it looks like:
formset_f = modelformset_factory(ProjectPage, form=ProjectPageForm, extra=3)
formset = formset_f(queryset=ProjectPage.objects.filter(page_project__id=proj), initial =[{'page_project': proj}, {'page_project': proj}, {'page_project': proj}])
Initial values now match number of extra forms - every form got it's own foreign key.
Probably there is a better solution, but the the problem is found and solved for me!
My problem was that when I tried to render every form of the formset manually I added an unneded <form></form> html element
wrong:
{ form.management_form }}
{% for form in formset %}
<form class="form-class">
{{form.name}}
</form>
right:
{ form.management_form }}
{% for form in formset %}
<div class="form-class">
{{form.name}}
</div>
After that change my forms were recognized correctly.

Edit Listing Form is Duplication

I have a listing system on my website and am currently creating a page which allows the user to edit their listing, I've got most of it working however I am stuck on saving their updated form. Currently if they save the edited form rather than updating the model it creates a whole new listing entry and still leaves the old one there. If anyone could please look at my code that would be great, I've been stuck on this problem for so long!
View -
#login_required(redirect_field_name='login')
def editlisting(request, pk):
post = JobListing.objects.get(pk=pk)
if str(request.user) != str(post.user):
return redirect("index")
if request.method == "POST":
print("test")
form = JobListingForm(request.POST, instance=post, force_update=True)
if form.is_valid():
form.save()
return redirect('index')
else:
print("else")
form = JobListingForm(instance=post)
context = {
"form": form
}
return render(request, "editlisting.html", context)
Model -
class JobListing(models.Model):
region_choice = (
('Auckland', 'Auckland'),
('Wellington', 'Wellington'),
('Christchurch', 'Christchurch')
)
industry_choice = (
('Accounting', 'Accounting'),
('Agriculture, fishing & forestry', 'Agriculture, fishing & forestry'),
('Automotive', 'Automotive'),
('Banking, finance & insurance', 'Banking, finance & insurance'),
('Construction & Architecture', 'Construction & Architecture'),
('Customer service', 'Customer service'),
)
employment_type_choice = (
('Full Time', 'Full Time'),
('Part Time', 'Part Time'),
('One-off', 'One-off'),
('Other', 'Other')
)
user = models.CharField(max_length=50)
job_title = models.CharField(max_length=30)
pay_rate = models.DecimalField(max_digits=10, decimal_places=2)
employment_type = models.CharField(max_length=10, choices=employment_type_choice)
job_description = models.CharField(max_length=2000)
business_address_region = models.CharField(max_length=50, choices=region_choice)
business_address_suburb = models.CharField(max_length=50)
business_industry = models.CharField(max_length=50, choices=industry_choice)
email = models.EmailField(max_length=50, blank=True, null="True")
telephone = models.IntegerField(blank=True, null='True')
active_listing = models.BooleanField(default=True)
class Meta:
verbose_name = 'Job Listing'
def clean(self):
if not (self.email or self.telephone):
raise ValidationError("You must specify either email or telephone")
if not self.email:
self.email = "Not Provided"
def __unicode__(self):
return "%s" % self.job_title
Piece of code from my registration app which could be affecting it?
def signup(self, request, user):
SignUpProfile.objects.create(
user=user,
account_type=self.cleaned_data['account_type'],
contact_number=self.cleaned_data['contact_number']
)
Form -
class JobListingForm(forms.ModelForm):
class Meta:
model = JobListing
fields = ['job_title', 'pay_rate', 'employment_type', 'job_description', 'business_address_region',
'business_address_suburb', 'business_industry', 'telephone', 'email']
widgets = {
'job_title': forms.TextInput(attrs={'class': 'form-input', 'placeholder': 'Job Title'}),
'pay_rate': forms.NumberInput(attrs={'class': 'form-input', 'placeholder': 'Hourly Rate or One Off Amount'}),
'employment_type': forms.Select(attrs={'class': 'form-input'}),
'job_description': forms.Textarea(attrs={'class': 'form-textarea',
'placeholder': 'Tell us additional information about your job listing e.g. Times, Business Info, Number of positions etc. (2000 Character Limit)'}),
'business_address_region': forms.Select(attrs={'class': 'form-input'}),
'business_address_suburb': forms.TextInput(attrs={'class': 'form-input', 'placeholder': 'Business Suburb'}),
'business_industry': forms.Select(attrs={'class': 'form-input'}),
'email': forms.EmailInput(attrs={'class': 'form-input', 'placeholder': 'Email'}),
'telephone': forms.NumberInput(attrs={'class': 'form-input', 'placeholder': 'Contact Numnber'}),
}
Form HTML -
<div id="createjoblisting">
<h1 class="pageheader">Edit Your Job Listing</h1>
<form class="createjoblisting" id="createjoblisting_form" method="post" action="{% url 'createjoblisting' %}">
{% csrf_token %}
{{ form.non_field_errors }}
<p> <label for="id_username" class="form-input-label">Job Title</label><br>
{{ form.job_title }}<br><p>{{ form.job_title.errors }}
<p><label for="id_username" class="form-input-label">Pay Rate</label><br>
{{ form.pay_rate }}<br></p>{{ form.pay_rate.errors }}
<p><label for="id_username" class="form-input-label">Employment Type</label><br>
{{ form.employment_type }}<br><p>{{ form.employment_type.errors }}
<p><label for="id_username" class="form-input-label">Job Description</label><br>
{{ form.job_description }}<br><p>{{ form.job_description.errors }}
<p><label for="id_username" class="form-input-label">Business Region</label><br>
{{ form.business_address_region }}<br><p>{{ form.business_address_region.errors }}
<p><label for="id_username" class="form-input-label">Business Suburb</label><br>
{{ form.business_address_suburb }}<br><p>{{ form.business_address_suburb.errors }}
<p><label for="id_username" class="form-input-label">Business Industry</label><br>
{{ form.business_industry }}<br><p>{{ form.business_industry.errors }}
<p><label for="id_username" class="form-input-label">Contact Number (Must provide either Contact Number or Email)</label><br>
{{ form.telephone }}<br><p>{{ form.telephone.errors }}
<p><label for="id_username" class="form-input-label">Email</label><br>
{{ form.email }}<br><p>{{ form.email.errors }}
<button type="submit" class="form-button">Update Job Listing</button>
</form>
</div>
URLS -
urlpatterns = [
url(r'^createjoblisting/', views.createjoblisting, name='createjoblisting'),
url(r'^(?P<pk>[0-9]+)/editprofile/', views.editprofile, name='editprofile'),
url(r'^(?P<pk>[0-9]+)/editlisting/', views.editlisting, name='editlisting'),
url(r'^editlistingportal/', views.editlistingportal, name='editlistingportal'),
]
Your form's action is wrong. Change it to:
<form action="{% url 'editlisting' %}" class="createjoblisting" id="createjoblisting_form" method="post" >
As you have copied the creation template, your form posts your data to the view which creates the listing instead of editing it.

Categories