Fill input field of foreignkeyfield from database in Django - django

I am using a foreignkey field of a model as an input field in the html form because I want a user input if the value is not present in the database. So I just gave an input tag and in views I take the value and assign it to the form field. Now if the userprofile is already created then the pincode value will be there. How can I prepopulate the input field in the html with the value from the database?
profile.html
<form method="POST" id="userProfileForm" enctype="multipart/form-data">
{% csrf_token %}
.
.
.
<div>
<label for="input_pincode">Pincode</label>
<input id="input_pincode" type="text" name="input_pincode">
</div><br>
.
.
.
</form>
models.py
class UserProfile(models.Model):
.
.
.
pincode = models.ForeignKey(Pincode, models.SET_NULL, blank=True, null=True)
forms.py
class UserProfileUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileUpdateForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
class Meta:
model = UserProfile
fields = ['pincode', other_fields]
views.py
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
up_form = UserProfileUpdateForm(request.POST, request.FILES, instance=request.user.userprofile)
if u_form.is_valid() and up_form.is_valid():
u_form.save()
uncommitted_up_form = up_form.save(commit=False)
if request.POST['city']:
pin = Pincode.objects.get_or_create(city_id=request.POST['city'], pincode=request.POST['input_pincode'])[0]
uncommitted_up_form.pincode = pin
#other logic
uncommitted_up_form.save()
messages.success(request, f'Your profile has been updated!')
return redirect('profile')
Here in the html file I want to show the value of userprofile.pincode.name in the input_pincode box. How can I do that?

This is an example of how to show the value of userprofile.pincode.name in the input_pincode box. You can try like this.
in views.py
name = userprofile.pincode.name
return render(request, "profile.html", {"name ": name }) OR return render(request,
"profile.html", {"name ": userprofile.pincode.name})
in HTML template
<form method="POST" id="userProfileForm" enctype="multipart/form-data">
{% csrf_token %}
<div>
<label for="input_pincode">Pincode</label>
<input id="input_pincode" value="{{name}}" type="text" name="input_pincode">
</div><br>
</form>

Related

Django - Passing the creator of a form to the form

I am making an auction site. I need to know per listing who the creator was (so the creators will have the possibility to delete the listing). It works for me to manually change the user in Django Admin, but I want it to be automatically saved when someone creates a new listing.
How do I pass the creator of a form to the form?
These are the relevant models:
class User(AbstractUser):
pass
class AuctionListing(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=512, default="")
starting_bid = models.DecimalField(max_digits=6, decimal_places=2, default=0.01, validators=[MinValueValidator(Decimal('0.01'))])
url = models.URLField(max_length=200, blank=True)
category = models.CharField(max_length = 20)
user = models.ForeignKey(User, on_delete=models.CASCADE, db_constraint=False, related_name="items")
def __str__(self):
return self.title
Here is my forms.py:
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
'user': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['user'].initial = user.id
And here was my attempt for the view:
def create_listing(request):
form = CreateListing(request.POST, user=request.user)
if request.method == "POST":
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
return render(request, "auctions/create_listing.html", {"form": form})
return render(request, "auctions/create_listing.html", {
"form" : CreateListing(user=request.user)
})
auctions/create_listing.html looks like this:
<h1> Create new listing </h1>
<form action="" method="POST">
{% csrf_token %}
<label>Name*</label>
<br>
{{ form.title }}
<br>
<label >Description*</label>
<br>
{{ form.description }}
<br>
<label >Starting bid*</label>
<br>
{{ form.starting_bid }}
<br>
<label > Image url (optional) </label>
<br>
{{ form.url }}
<br>
<label > Category (optional) </label>
<br>
{{ form.category }}
<br>
{{ form.user }}
<button type="submit" class="btn btn-primary save">Create your listing</button>
</form>
The error I get with this is: "BaseModelForm.init() got an unexpected keyword argument 'user'"
How can I fix this so the user will automatically be saved each time a listing is created?
Add user argument in the __init__ method of the form. You can set the user right there and there is no need for even displaying the user field. You can completely hide it.
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
'user': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['user'].initial = user.id
Remember to use the user kwarg in the view:
def create_listing(request):
form = CreateListing(request.POST, user=request.user)
if request.method == "POST":
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
# If form is invalid you should render the same template again
# with the errors
return render(request, "auctions/create_listing.html", {"form": form})
return render(request, "auctions/create_listing.html", {
# For the empty form, this needs to be an instance of the form,
# and not a class
"form" : CreateListing(user=request.user)
})
Also, you can replace your HTML with:
{{ form.user }}
Replace {{ form.user }} by <input type="hidden" name="user" value="{{request.user}}">
User has to come automatically so you don't need to display user field in the front-end
by the above method you'll get logged in user but still hard to save as it is foreign key, what ever you get from front-end it'll be string type.
So best suggestion is the below code.
if form.is_valid():
form_data = form.save()
form_data.user = request.user
form_data.save()

Django custon form with validate

I have some problem with the form and Django.
I would like to do a custom (in column and with style) form from a model. But after few hours to try I thinks it's not possible.
So I decide to create not a forms.ModelForm but a forms.Form, in order to custom my form. But in this way i can't keep the validations...
And last thing I try, it in the template file to write a validation manually, it's work but when I submit my form with error, and when it's refresh, all the data are loose, and I see just the error message...
So it make me crazy... I just would like to do a nice form with django...
Thanks in advance
forms.py
class PatienceForm(forms.ModelForm):
class Meta:
model = Patience
fields = ('nom', 'prenom', 'age', 'email')
template.html
<form method="POST" accept-charset="utf-8">
{% csrf_token %}
<p><label for="id_nom">Nom :</label> <input type="text" name="nom" maxlength="200" required id="id_nom"></p>
<p><label for="id_prenom">Prenom :</label> <input type="text" name="prenom" maxlength="200" required id="id_prenom"></p>
<p><label for="id_age">Age :</label> <input type="number" name="age" required id="id_age"></p>
<p><label for="id_email">Email :</label> <input type="email" name="email" maxlength="254" required id="id_email"></p>
{% for err in form.email.errors %}
{{err}}
{% endfor %}
<button type="submit" class="save btn btn-default">Save</button>
view.py
def post_essaie(request):
if request.method == "POST":
form = PatienceForm(request.POST)
if form.is_valid():
logging.info('Hello')
post = form.save(commit=False)
post.published_date = timezone.now()
post.save()
return render(request, 'blog/succes.html')
return render(request, 'blog/teste.html', {'form': form})
else:
form = PatienceForm()
return render(request, 'blog/teste.html', {'form': form})
Thanks in advance for your help
for your form.py :
class PatienceForm(forms.Form):
nom = forms.CharField(max_length=200,label='Nom')
prenom = forms.CharField(max_length=200)
age = forms.integerField(max_length=200)
email = forms.EmailField(max_length=254)
# use clean to verify your form
def clean(self):
cleaned_data = super(ContactForm, self).clean()
nom = cleaned_data.get('nom')
prenom = cleaned_data.get('prenom')
age = cleaned_data.get('age')
email = cleaned_data.get('email')
if not name and not email and not message:
raise forms.ValidationError('le formulaire est vide')
in your views.py you can use :
from django.shortcuts import render
from .forms import ContactForm
def post_essaie(request):
if request.method == 'POST':
form = PatienceForm(request.POST)
if form.is_valid():
logging.info('Hello')
nom = form.cleaned_data['nom']
prenom = form.cleaned_data['prenom']
age = form.cleaned_data['age']
email = form.cleaned_data['email']
# here create your entry with all the data from your form then add
# your published_date
post = Patience(nom=nom, prenom=prenom, age=age,
email=email, published_date = timezone.now())
post.save()
return render(request, 'blog/succes.html')
else:
form = PatienceForm()
return render(request, 'blog/teste.html', {'form': form})
Voila Bonne journée !!

User avatar not displayed in Django

I want to user have a avatar. So I created the model and the form.
Image is not displaying on the page. But form saves the image to folder. Where is mistake?
request.user.avatar.url doesn't work. Maybe the image is not attached to User? Thanks for the help
P.S. djagno-avatar is not good for me.
models.py
class Avatar(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT, null=True)
avatar = models.ImageField(upload_to='user_avatars', null=True)
forms.py
class UserPhotoForm(forms.ModelForm):
class Meta:
model = Avatar
fields = ('avatar', )
widgets = {
'avatar': forms.FileInput(attrs={'class': 'input'}),
}
views.py
def cabinet(request):
user = request.user
if request.method == 'POST':
form = UserPhotoForm(request.POST, request.FILES, instance=user)
if form.is_valid():
form.save()
else:
form = UserPhotoForm()
return render(request, 'account/cabinet/cabinet.html', {'form': form})
cabinet.html
<div class="avatar">
{{ request.user.avatar.url }} #there is trying
{{ request.user.avatar.avatar.url }}
<img src="{{ request.user.avatar.avatar.url }}" alt="" width="80px" height="80px">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" id="file"/>
</form>
try this
<img src="{{ request.user.avatar.url }}" alt="" width="80px" height="80px">
https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.ImageField
Found the main problem you are never storing your avatar model in db. As you are giving it the instance of your user. Because of that your Avatar model is not stored.
You have to use
def cabinet(request):
user = request.user
if request.method == 'POST':
form = UserPhotoForm(request.POST,request.FILES)
if form.is_valid():
temp=form.save(commit=False)
temp.user = user
temp.save()
else:
form = UserPhotoForm()
return render(request, 'account/cabinet/cabinet.html', {'form': form})
Try that

Django MultiValueDictKeyError for upload file

There has a file upload page for upload file to a object by id in model. However, it shown MultiValueDictKeyError after submitted. I would appreciate if any help.
models.py:
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
items = models.ManyToManyField(OrderItem)
img_upload = models.FileField(upload_to='payment', null=True)
forms.py:
class Upload_File(forms.Form):
class Meta:
model = Order
fields = ('img_upload')
views.py:
def upload_page(request, id):
order = get_object_or_404(Order, id=id)
form = Upload_File(request.POST or None, request.FILES or None)
if request.method == 'POST':
order.img_upload = request.FILES['file']
if form.is_valid():
form.save()
messages.success(request, 'Succeed')
return redirect('user_info')
else:
form = Upload_File()
context = {
'form': form,
}
return render(request, 'upload.html', context)
html:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input class="form-group" type="file" name="file">
<button class="form-group" type="submit">Submit</button>
</form>

Saving image fails without error in django model form

I want to try to save an image to my model:
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)
class Leverandor(models.Model):
ID = models.AutoField(primary_key=True)
UserID = models.ForeignKey('Stamdata', on_delete=models.CASCADE)
Name = models.CharField('Name', max_length=200)
URL = models.URLField('URL', max_length=200)
ImageURL = models.ImageField('ImageURL',blank=True, null=True, upload_to=user_directory_path)
To this Form.py:
class EditLeverandorForm(forms.ModelForm):
Name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
URL = forms.URLField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
ImageURL = forms.ImageField
class Meta:
model = Leverandor
labels = {
'Name' : 'Leverandør',
'URL' : 'Webside',
'ImageURL' : 'Logo',
}
fields = ['UserID', 'Name', 'URL', 'ImageURL']
And rendererd to this view.py
def add_leverandorer(request):
user_id = request.user.id
# if this is a POST request we need to process the form data
if request.method == 'POST':
print (user_id)
form = EditLeverandorForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
form.save()
return HttpResponseRedirect('/backend/leverandorer')
else:
print ('somethin goes wrong')
print (user_id)
form = EditLeverandorForm()
return render(
request,
'backend/add_leverandorer.html',
{
'title':'WestcoastShop - Backend',
'form': form,
}
)
The problem is that before I add the instance=request.user part its saves the entry correct but without image. Now I add the part from Django documentation like provided for save to an variable path but nothing happened after i click to save button.
<form action="/backend/leverandorer/add" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="simpleinput">Leverandør</label>
{{ form.Name }}
</div>
<div class="form-group">
<label for="simpleinput">Webside</label>
{{ form.URL }}
</div>
<div class="form-group">
<label for="simpleinput">Logo</label>
{{ form.ImageURL }}
<!--<input type="file" name="ImageURL" accept="image/*" required="" id="id_ImageURL" class="form-control-file">-->
</div>
<input type="hidden" id="UserID" name="UserID" value="{{ user.id }}">
<button type="submit" class="btn btn-primary">Gem</button>
</form>
I didnt see an error but now its not saving the form in models also if ImageField is empty.
regards
Christopher.
You are using UserID as a hidden field. The hidden field will not pass the form-validation. So your following code will be false.
if form.is_valid():
form.save()
return HttpResponseRedirect('/backend/leverandorer')
One of the solutions is, remove the UserID field from your template and update your view as follows.
if form.is_valid():
user_form = form.save(commit=False)
user_form.UserID = request.user
user_form.save()
I I change the function in models.py to:
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.UserID, filename)
class Leverandor(models.Model):
ID = models.AutoField(primary_key=True)
UserID = models.ForeignKey('Stamdata', on_delete=models.CASCADE)
Name = models.CharField('Name', max_length=200)
URL = models.URLField('URL', max_length=200)
ImageURL = models.ImageField('ImageURL',blank=True, null=True, upload_to=user_directory_path)
its works, but the Path is Username and not user.id