Form not populating data

Need a second set of eyes on this. Cannot figure out why data is not going to the form.

template

{% extends 'base.html' %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    <title>Document</title>

</head>
<body>
    {% block body %}
    <div class="container mt-2">
    <form  method="POST" >
        {% csrf_token %}
        <br><h1><center>Send Email</center></h1><br>
        <center>{{ form.as_p }}</center>
        </div><br><br>
        <center><input type="submit" value="Send" style="background-color: rgb(8, 167, 8); color: white; height:38px; width:70px; padding-bottom: 6px;">
        <a href="{% url 'index' %}" class="btn btn-danger">Cancel</button></a></center>
        </div> 
        
    </form>
    </div>
    
    {% endblock body %}
    
</body>
</html>

form

class EmailNewForm(forms.ModelForm):
    orginal_message = forms.CharField(max_length=500, widget=forms.Textarea, required=True, label='Email Message')
    # m28t_sender = forms.CharField(max_length=50, disabled=True)
    # m28t_receiver = forms.CharField(max_length=50, disabled=True)
 

    class Meta:
        model = M28tEmails
        fields = ('m28t_sender',
                  'm28t_receiver',
                  'orginal_message',
                 )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(kwargs, args, self.instance)

        # m28t_sender = CustomUser.objects.filter(id=self.instance.id).values('id')
        # self.fields['m28t_sender'] = m28t_sender

view

@login_required
def email_new(request, sponsor, id):
    if request.method == "POST":
        form = (request.POST)
        if form.is_valid():
            form.save()
            # owner = CustomUser.objects.filter(pk=request.user.id).get()
            # Organization.objects.filter(org_name=form.cleaned_data['org_name']).update(org_owner=owner.pk)
        return render(request, 'index.html', {'form': form})
    else:
        form = EmailNewForm()
        return render(request, "accounts/email_new_form.html", {'form': form})

url

path('email_new/<int:id>/<int:sponsor>/', views.email_new, name='accounts/email_new'),

output

{} () None, None, None, None, None, None
[06/Nov/2023 11:26:22] "GET /accounts/email_new/34/2/ HTTP/1.1" 200 5811

Ids are sent for receiver 34 and sponsor 2

1 Like

You’re not creating an instance of a form here. This should be something like form = EmailNewForm(request.POST)

Also, you’re not passing an instance as a parameter to that constructor, either, so there will not be an existing instance for you to check.

Why is it not creating an instance?

Why is what not creating an instance? (Please specify what code you’re referring to.)

def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(self.instance)

I do not understand why this is empty.

I answered this here: Form not populating data - #2 by KenWhitesell

Additionally, for the printed output that you are displaying, the output is associated with a GET and not a POST. You are initializing a blank form here:

You are not supplying an instance of an object to initialize this form, so the form is empty.

"You are not supplying an instance of an object to initialize this form, so the form is empty.’

I guess the question is how do I get the two id’s in the URL to use in the form?

Use how?

You show parameters being passed to your view named sponsor and id.

Your form shows fields named m28t_sender, m28t_receiver, and original_message.

You reference a model named M28tEmails which you have not shown here.

So I don’t know how those parameters are supposed to match up with your form.

model

class M28tEmails(models.Model):
    m28t_sender = models.BigIntegerField(null=True, blank=True)
    m28t_receiver = models.BigIntegerField(null=True, blank=True)
    # m28t_org = models.BigIntegerField(null=True, blank=True)
    orginal_message = models.CharField(max_length=500, null=True, blank=True)
    cleaned_message = models.CharField(max_length=500, null=True, blank=True)
    m28t_email_time = models.DateTimeField(null=True, blank=True)
    m28t_uid = models.BigIntegerField(blank=True, null=True)
    m28t_email_flagged = models.BooleanField(default=False, null=True, blank=True)

    class Meta:
        ordering = ['m28t_sender', 'm28t_receiver', 'orginal_message', 'cleaned_message', 'm28t_email_time'] 


    def __str__(self):
        return f'{self.m28t_sender}, {self.m28t_receiver}, {self.m28t_email_time}, {self.orginal_message}, {self.cleaned_message}' 

I have what I need and cannot get it to populate in the form. jeff_l0000 should populate the email_from.

form

class EmailNewForm(forms.ModelForm):
    email_from = forms.CharField(max_length=50)

    class Meta:
        model = Emails
        fields = ('sender',
                  'email_from',
                  'recipient',
                  )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(args)
        print(args[0]['sender'], args[0]['recipient'])

        email_from = CustomUser.objects.filter(id=args[0]['sender']).values('alias_name')[0]['alias_name']
        self.fields['email_from'] = email_from
        print(email_from)

output

({'sender': 2, 'recipient': 34},)
2 34
jeff_l0000

error

'str' object has no attribute 'get_bound_field'

Request Method: 	GET
Request URL: 	http://127.0.0.1:8000/accounts/email_new/34/2/
Django Version: 	4.2.6
Exception Type: 	AttributeError
Exception Value: 	

'str' object has no attribute 'get_bound_field'

Exception Location: 	D:\Programs\Python\Python312\Lib\site-packages\django\forms\forms.py, line 189, in __getitem__
Raised during: 	accounts.views.email_new
Python Executable: 	D:\Programs\Python\Python312\python.exe
Python Version: 	3.12.0
Python Path: 	

['D:\\OneDrive\\RockTech\\Django Projects\\m28t',
 'D:\\Programs\\Python\\Python312\\python312.zip',
 'D:\\Programs\\Python\\Python312\\DLLs',
 'D:\\Programs\\Python\\Python312\\Lib',
 'D:\\Programs\\Python\\Python312',
 'D:\\Programs\\Python\\Python312\\Lib\\site-packages']

Server time: 	Tue, 07 Nov 2023 01:17:00 +0000

If I add this below, it does not get the error but the field is not populated.

self.fields['email_from'].charfield = email_from

In your view, not your form, you initialize a form as:

form = FormClass(...)

You can use the initial parameter to set the initial values for form fields.

That means that you would make this query in the view:
email_from = CustomUser.objects.filter(id=args[0]['sender']).values('alias_name')[0]['alias_name']

Side note: This query can be simplified as something like:
email_from = CustomUser.objects.get(id=request.user.id).alias_name

and pass it to the form as:
form = EmailNewForm(initial={'email_from': email_from})

This completely removes the need for anything to be done in the __init__ method in the form.

Thanks much and is there a way to make it uneditable on the form? When I do disable it does not show the value.

Why have it as a field then? I’d render it on the page as a literal value.

If the field is marked as disabled, then the POST of the form is not going to include it in the data being returned. You’ll have to issue the query at that point again anyway.

I would prefer that, but could only get the request to use in the template and could not send context to form and template. Is there a way to do that?

How are you currently creating your context? (Or, to phrase this slightly differently, what part of your view specifies what the context is? Specifically, what line of code?)

 else:
        recipient_alias = CustomUser.objects.filter(id=recipient).values('alias_name')[0]['alias_name']
        sender_alias = CustomUser.objects.filter(id=sender).values('alias_name')[0]['alias_name']
        context = {
            'sender': sender,
            'recipient': recipient,
            'sender_alias': sender_alias,
            'recipient_alias': recipient_alias,

        }
        form = forms.EmailNewForm(context)
        return render(request, "accounts/email_new.html", {"form": form})

What is the one line of code where the context is defined. (Not the contents of the context, which is most of what you posted here, but the context itself.)

@login_required
def email_new(request, recipient, sender):
    if request.method == "POST":
        form = forms.EmailNewForm(request.POST)
        if form.is_valid():
            sender_email = CustomUser.objects.filter(id=sender).get()
            recipient_email = CustomUser.objects.filter(id=recipient).get()
            print(sender_email.alias_email, recipient_email.alias_email)
            subject = f'Message from {sender_email.alias_email}.'
            message = {form.cleaned_data['orginal_message']}

            # send_mail(subject, message, sender_email, [recipient_email.email], html_message=message,)
            form = forms.EmailNewForm()
            return redirect('index.html')
    else:
        recipient_alias = CustomUser.objects.filter(id=recipient).values('alias_name')[0]['alias_name']
        sender_alias = CustomUser.objects.filter(id=sender).values('alias_name')[0]['alias_name']
        context = {
            'sender': sender,
            'recipient': recipient,
            'sender_alias': sender_alias,
            'recipient_alias': recipient_alias,

        }
        form = forms.EmailNewForm(context)
        return render(request, "accounts/email_new.html", {"form": form})

Ok, let me try rephrasing the question. What is a context when talking about rendering a page? (What data type is it?)