Django template not showing form instance value - python

I am new to django and building an user (named "Developer") settings update page. I used model form and passed the settings instance via views.py hoping them to show up in the rendered template for users (named "Developer") to edit. But the instance value is not populated into the template in form.as_p.
I have tested the {{project_form.instance.pk}} is passing the correct project instance, so I am expecting the project name to show up as default value in the form for user input project name, but it is showing blank.
models.py (simplified)
class Project(models.Model):
project_name = models.TextField(unique=True)
class Developer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE, default=Project.get_default_project)
institution = models.ForeignKey(Institution, on_delete=models.CASCADE, null=True, blank=True)
forms.py
class ProjectForm(ModelForm):
class Meta:
model = Project
fields = ['project_name']
views.py
def developerSettingsUpdate(request):
from .forms import ProjectForm
developer = request.user.developer
project = developer.project
if request.method == 'POST':
project_form = ProjectForm(request.POST, instance=project)
if project_form.is_valid():
project_form.save()
else:
project_form = ProjectForm(instance=project)
return render(request,
'decg/developer_settings.html',
{
'project_instance': project,
'project_form': project_form,
})
developer_settings.html
<div>
<h5>Expecting this field to show instance: {{ project_form.instance.project_name }}</h5>
</div>
<form method="post">
{% csrf_token %}
{{ project_form.as_p }}
<button class="button" type="submit">Update</button>
</form>
But it is showing blank: see Screenshot of rendered developer_settings.html:
see Screenshot of rendered developer_settings.html

The problem lies in this code:
developer = request.user.developer
project = developer.project
Those variables must point to an actual model instance in order to populate the form like you did in project_form = ProjectForm(instance=project) . It should be something like this:
developer = Developer.objects.filter(user=request.user.developer)
project = Project.objects.filter(project_name=request.user.developer)

Related

Updating a django form involving 2 seperate functions (template function & form specific function)

I am trying to a update a form from a separate function.
By clicking on button "Add" the existing form is updated by adding a user to the form.
Adding the user to the form works fine. However I am loosing the text input from the initial form when submitting my update.
The reason why I am using 2 functions is because I have multiple forms on the same template: each form is redirected to a specific url defined in action="{% url %}"
The usual way I use to update a form is as follows:
def function(request, id)
instance = get_object_or_404(Model, pk=id)
data = Model(request.POST or None, instance = instance)
This is not working in this case because I need to provide the instance_id on the parent function, but the id parameter is provided on the function that supports the form. (child function)
I suppose there is 2 options/questions:
Can I access the form_id from the parent function?
Should I deal with this in the form function? and in this case how do I keep the
existing text when updating form?
model
class UserProfile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
class Model(models.Model):
user = models.ManyToManyField(User, blank=True)
text = models.TextField('text', blank=True)
template (main/parentfunctiontemplate.html)
{%for model in a %}
<form action="{%url 'child-function' userprofile.id model.id%}" method="POST">
{% csrf_token %}
<input type="Submit" value="Add" class="btn btn-primary custom-btn">
</form>
{%endfor%}
view
def parent_function(request, userprofile_id):
a = Model.objects.filter(venue=request.user.userprofile.venue)
updateform=ModelForm()
return render(request,"main/parentfunctiontemplate.html",{'updateform':updateform,'a':a})
def child_function(request, userprofile_id,model_id):
url = request.META.get('HTTP_REFERER')
userprofile = get_object_or_404(UserProfile, pk=userprofile_id)
instance = get_object_or_404(Model, pk=model_id)
updateform = ModelForm(request.POST or None, instance = instance)
if updateform.is_valid():
data = updateform.save(commit=False)
data.save()
updateform.save_m2m()
current_model_instance = get_object_or_404(Model, id=data.id)
current_model_instance.user.add(userprofile.id)
return redirect(url)
else:
print(updateform.errors)
return redirect('main/parentfunctiontemplate.html',{'userprofile':userprofile,'instance ':instance })
form
class ModelForm(ModelForm):
class Meta:
model = Model
fields = ('text')

Select2 widget showing on Django Admin site but not on the form template in Django4

I have two object models, NewsObject and StockObject. The stock object is a foreign key in the news object.
class stockObject(models.Model):
stock_name = CharField(max_length=100, blank=True, null=True)
stock_tag = CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.stock_name
class newsObject(models.Model):
title = CharField(max_length=100, blank=True, null=True)
body = TextField(blank=True, null=True)
stock = ForeignKey(stockObject, on_delete=models.SET_NULL, blank=True, null=True)
I have used autocomplete_fields property in the ModelAdmin class as I want a searchable dropdown for stocks in news. I have also added search_fields in the stocks ModelAdmin as mentioned in the documentation.
This is what my admin.py looks like:
class stockAdmin(admin.ModelAdmin):
list_display = ['stock_name', 'stock_tag']
search_fields = ['stock_name']
class newsAdmin(admin.ModelAdmin):
list_display = ['title', 'body', 'stock']
search_fields = ['title', 'body', 'stock']
autocomplete_fields = ['stock']
Now, the issue is that I get a searchable dropdown on the Django Admin site for this field, but it is only a dropdown (not searchable) on the actual template screen. I have a basic view which calls the template, like so:
Views.py
def createNews(request):
form = NewsForm()
if request.method == 'POST':
form = NewsForm(request.POST)
if form.is_valid():
form.save()
return redirect('/backoffice/')
context = {'form' : form}
return render(request, 'NewsForm.html', context)
And NewsForm.html is:
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" name="Submit">
</form>
{% endblock %}
I've been wondering what might be the cause of this behavior. Tried multiple things but none of them work. What might I be missing here?
Django Admin site image
Django Template Image
I think you have written all your models in camelCase so first changed them to PascalCase.
Second, you have missed models in all your models:
Write them like this add models before every datatype like:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
Not only datatype of fields.

Creating a Dynamic Form in Django

i'm currently working on a project that would have a database of reports of a scam. In the report section of the website I have a form, but I want anyone to be able to add multiple profiles with a click of a button. For example:
Nickname field: xyz
Steam profile: x
[ + ] <- button for adding more profiles, which when pressed would look something like this:
Nickname field: xyz
Steam profile: x
Steam profile 2: y [ Delete ]
[ + ]
I was looking into FormSets and Inline Formsets, but nothing turned up that would match this specific need, aswell as did not answer the question regarding storing the results of the form.
How would I go about creating the form for this?
How would I store the multiple results of Steam profile to my object that has a steam_profile = models.CharField?
My current model:
class Scammer(models.Model):
#Basic information for display
steam_id_64 = models.CharField(max_length=17, default='00000000000000000')
nickname = models.CharField(max_length=64, default='Nickname')
steam_profile = models.CharField(max_length=512, default='https://www.steamcommunity.com')
description = models.TextField(default='')
proof = models.TextField(default='')
#Date created var for ordering
date_created = models.DateTimeField(default=timezone.now, blank=True)
def __str__(self):
return self.nickname
def get_absolute_url(self):
return reverse('dashboard-home')
My view:
class ScammerCreateView(CreateView):
model = Scammer_Unapproved
template_name='dashboard/report.html'
fields = ['nickname', 'steam_id_64', 'steam_profile', 'description', 'proof']
My template:
{% block content %}
<div class="report-scammer">
<form method="POST">
{% csrf_token %}
<fieldset>
<legend>Report a scammer</legend>
{{ form|crispy }}
</fieldset>
<div>
<button type="submit">Report</button>
</div>
</form>
</div>
{% endblock content %}
Have the profiles as the Builtin Django User model or maintain a separate model with a link to the inbuilt User model. Now the scam report form can have the option to be linked to Multiple User accounts by using ManytoMany relationship field. check the below official documentation page,
[https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/][1]

Bringing Information from django.contrib.auth.models.User into View

I have the following model in my Django project:
from django.contrib.auth.models import User
class Project(models.Model):
project_title = models.CharField(max_length=200)
project_description = models.CharField(max_length=200, default="")
created_date = models.DateTimeField('date created')
owner = models.ForeignKey(User)
def __str__(self):
return self.project_title
This view uses the Project model as follows:
class ProjectView(generic.edit.UpdateView):
model = Project
fields = ['project_title','project_description']
template_name = 'steps/project.html'
success_url = reverse_lazy('steps:index')
My question is how can I bring the User's fields into my ProjectView so I can then use them in templates? In particular, I would like to display the logged-in user's name and email.
user information placed on request, not on views. So you can write in template {{user.username}}, or {{user.email}}. and you'll get it. Of course if user.is_authenticated
in your template write:
{% if request.user.is_authenticated %}
{{ request.user.username }}
{{ request.user.email }}
{% endif %}

Attaching a current User object to Django form

I am working on an app that has a section with with a file upload form for .txt fiels. I would like for the current user that is uploading the file to be added along with the file and the file name. Currently, I can do this successfully in the admin section but I just cant get it to save via the form itself. Any Ideas?
Here are the models:
class UploadedTextFile(models.Model):
file = models.FileField(upload_to="textfiles")
filename = models.CharField(max_length = 50)
username = models.ForeignKey(User, blank=True, null=True)
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
Here is my view:
def inputtest(request):
#response for file being submited
if request.method == "POST":
form = UploadedTextFileForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
new_form.username = request.user
new_form.save()
return render(request, 'about.html')
inputtest = UploadedTextFileForm()
return render(request, 'failed.html', {'inputtest': inputtest})
else:
inputtest = UploadedTextFileForm()
return render(request, 'inputtest.html', {'inputtest': inputtest})
Here is my html:
{% extends 'base.html' %}
{% block content %}
<form method="post">{% csrf_token %}
{{ inputtest.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Doing it in the view (as you've shown) is the right way to do this. Most likely you're having problems because you've left username as a field on the form, and because the FK model field doesn't have blank=True set the form requires the field to be provided. You should explicitly declare just the subset fields that you want to accept user input for in the form's Meta class.
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
I am not sure why you're rendering a different template when the form is not valid, but no matter what you're not providing the form object in the context. This means that you'll never see any errors the form detects, which is probably what's happening with this code - you're not seeing the error that username is not provided.

Categories

Resources