How to get all OneToOne model Fields in other model form

its a simple problem forgive me if i didn’t understand how to solve it but really don’t know how or forget how
i have a Post model

class Post(models.Model):
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
    title = models.CharField(max_length=200, db_index=True, blank=False, default='')
    snippet = models.OneToOneField(Snippet, on_delete=models.CASCADE, related_name='post_snippets', blank=True, null=True)
    creator = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="post_creator")
    ...

and Snippet model

class Snippet(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=100, blank=True, default='')
    code = models.TextField()

and simple form

class PostUpdateForm(forms.ModelForm):
    tag = forms.ModelChoiceField(queryset=Tag.objects.all(), widget=forms.Select())
    genre = forms.ModelChoiceField(queryset=Genre.objects.all(), widget=forms.Select())
    class Meta:
        model = Post
        exclude = ('views', 'creator', 'maintainer', 'snippet')

and the view is simplest

@login_required
def edit_post(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == 'POST':
        form = PostUpdateForm(request.POST, request.FILES, instance=post) 
        if form.is_valid():
            form.save()
            messages.success(request, _('Your profile has been successfully updated!'))
            return redirect('blog:details',  post.pk)
        else:
            messages.error(request, _('Please correct the following error.'))
    else:
        form = PostUpdateForm(instance=post)
    context = {'post': form}
    return render(request, 'blog/post_form.html', context)

if a post has been created without a snippet i can go to edit page to see all post fields

but if the post has been created with a snippet, when i go to edit page i can’t see all the snippet fields

sure i didn’t exclude the snippet field from the model to have all field but i will see only the related snippet field as a choices
but i want all the snippet fields to be shown in the post form to be edited if the post has already snippet fields

i have tried this form

class PostUpdateForm(forms.ModelForm):
    #add_code = forms.BooleanField(widget=forms.CheckboxInput(attrs={'class': 'checkbox', 'id': 'post-snippet'}), required=False)# attr. for JS addEvent or css styling
    tag = forms.ModelChoiceField(queryset=Tag.objects.all(), widget=forms.Select())
    genre = forms.ModelChoiceField(queryset=Genre.objects.all(), widget=forms.Select())
    class Meta:
        model = Post
        #fields = '__all__'
        #fields = ['title', 'tag', 'maintainer', 'post_img', 'content', 'snippet', 'genre', 'post_language', 'video', 'post_type', 'urls', 'views', 'status' ]
        exclude = ('creator', 'views')
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields('snippet_title', 'code', 'linenos', 'language', 'style', 'highlighted').queryset = Snippet.objects.all()
        # override clean(self): method if you have any logical operations for any fields see (an invalid form control file)
    def clean(self):
        cleaned_data = super().clean()
        # if this Item already exists
        if self.instance.add_code:
            # add the old quantity to the new quantity
            cleaned_data['snippet_title', 'code', 'linenos', 'language', 'style', 'highlighted'] = self.instance.snippet
        return cleaned_data
    def save(self, commit=True):
        post, created = Post.objects.update_or_create(snippet=self.snippet, creator=self.creator)
        #rest of your logic
        return post

but it gives me

TypeError at /blog/posts/884483e4-0102-4ca1-b7b4-66a9d8282f62/update/
'dict' object is not callable

how to get all snippet fields inside the form and not like choices
Screenshot 2022-11-28 at 1.07.45 PM
please some help bother @KenWhitesell

For this most recent attempt, what does the blog/post_form.html template look like? (Are you rendering a form named snpt in the template?)

Side note: It’s probably not a good idea to use get_object_or_404 inside a try / except block - you’re not doing anything with the 404 response that it’s creating if the requested object doesn’t exist. You can use the get function and catch the DoesNotExist exception directly.

here is the post form template

                    <form method='POST' id="form-container" class="form" enctype='multipart/form-data'>
                        {{ formset.non_field_errors }} {% csrf_token %} {% for field in form %}
                        <div class="post-form ">
                            {% if field.errors %}
                            <ol>
                                {% for error in field.errors %}
                                <li><strong>{{ error|escape }}</strong></li>
                                {% endfor %}
                            </ol>
                            {% endif %} {% if field.help_text %}
                            <p class="help">{{ field.help_text|safe }}</p>
                            {% endif %} {% endfor %}
                            <div class="form1">{% bootstrap_form post %}</div>
                            {% if form.snpt %}
                            <div class="form2">{% bootstrap_form snpt %}</div>{% endif %}
                        </div>
                        <button class="boxed-btn3 w-100" type="submit">Post</button>
                    </form>

i have changed get_object_or_404 to snippet = Snippet.objects.get(pk=post.pk) but i think i have to change the form to something that has a widgets for all snippet fields or something i don’t know

What object named form are you passing in to the template? (I don’t see one.)

i was trying another form before and i have changed it to just
if snpt only
but didn’t got the snippet fields too with views that has conditional snippet or the normal one that has only postUpdate form
also
i have removed this {% if snpt %} line for trying to render the post that has already snippet fields inside but got

Parameter "form" should contain a valid Django Form

because of
{% bootstrap_form snpt %}
what’s wrong with it??
it should work fine
i think that this is not the cause of the error but the form or view has something missed

You have a case where you don’t have snpt in the context. My guess is that that would cause this issue. (Trying to render the form with the bootstrap_form tag but not supplying a form.)

but the view is returning really both
context = {'post': post_form, 'snpt': snippet_form}
i really got confused from this error a lot
if the post has no snippet there is another context

context = {'post': post_form}

If any exception is thrown in this try block, then you’re not supplying the snpt form.

but the post i am trying to render to edit has snippet when created i am sure
i have created a lot of posts with snippets to see if they will be rendered with the snippets fields but no way

        post_form = PostUpdateForm(instance=post)
        try:
            snippet = Snippet.objects.get(pk=post.pk)  # should be true because it has already one
            snippet_form = SnippetUpdateForm(instance=snippet)
            context = {'post': post_form, 'snpt': snippet_form}
        except:
            context = {'post': post_form}

i have removed the form snpt from template and got the post form but with snippet as usual one field choices
what to do then to get it as a fields not related fields one to one?

This is most likely not going to be true - you’re trying to compare the pks between the two related objects, but there’s no requirement that those pks be the same.

You don’t need to issue a separate query to retrieve the snippet related to a post.

If you have a Post named post, then post.snippet is the related Snippet object (if it exists). If post.snippet is null, then there’s no related object.

yes you are right i know that you haver told me that it’s not condition that they will have the same id or pk in the database but
i have tried this before as just
snpt = post.snippet
but got it as only choice field too
i always having snippet as one individual field but i want it’s all field separately
i don’t know how to do it ?

But post.snippet is not a form (snpt). post.snippet is a Snippet. You still need to create the snpt form from that instance.

1 Like

**got it pro i gave it to the snippet form to get it and it worked finally , now i will see if i can edit and save the changes or i will have another problem **
i will back to you later if i got any problem but for now god bless you always my dear brother @KenWhitesell

i have a Question Brother @KenWhitesell
i had a problem in saving changes to the database using edit views but i found what caused this error

class PostUpdateForm(forms.ModelForm):
    tag = forms.ModelChoiceField(queryset=Tag.objects.all(), widget=forms.Select())
    genre = forms.ModelChoiceField(queryset=Genre.objects.all(), widget=forms.Select())
    class Meta:
        model = Post
        exclude = ('views', 'creator', 'maintainer', 'snippet')

**The form tag and genre widgets was causing the form to be not valid **
may i ask you to explain to me why these two fields of Model choice field causing this error please??

What are the complete errors being thrown by the validators for these fields?

no any thing is thrown i just stayed at the same page and scrolled up and nothing in console or even terminal, if there is something else i can do to check the validity tell me cause i really feel like stupid and dummy to not be able to distinguish this kind of errors
after removing these two fields from the form it’s now saving normally indeed
so my question is what was wrong in these two fields to cause the form to not saving?

You could print the errors in the console, or you can render them in your form template. See Working with forms | Django documentation | Django and The Forms API | Django documentation | Django for ideas in both areas. (Rendering in template and printing on console.)

Okay bro you have Done over the required really and i am grateful to you for your patience on me and real helping, god bless you again and thanks, i will try to use print and rendering both fields in the template to see what i get